Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add $readable and $writable runes #9237

Closed
vd-aloker opened this issue Sep 21, 2023 · 14 comments
Closed

Add $readable and $writable runes #9237

vd-aloker opened this issue Sep 21, 2023 · 14 comments
Labels

Comments

@vd-aloker
Copy link

Describe the problem

With stores, it's easy to pass a store to a function and have the function read or write its value:

function doSomething(theStore){
  const current = get(theStore);
  // ...
  theStore.set('New value')
}

let val = writable('')
doSomething(val)

With state runes, it's not as easy, because the underlying signal is not exposed. Now I'd have to pass in an object that wraps access to the state:

export function doSomethingWithState(state){
  const current = state.value;
  // ...
  state.value = 'New Value'
}

let val2 = $state('');

doSomethingWithState({ 
	get value() { return val2}, 
	set value(newValue) { val2 = newValue}
})

As far as I can see, there's no way to create a helper function or similar that could simplify this. As a result, I expect more boilerplate code when using state as a replacement for stores.

Describe the proposed solution

Given that it's not possible to create a helper function that creates the wrapper object, maybe it could prove useful to have $readable and $writable runes that cause the compiler to create those wrappers. $writable would add the setter, $readable would omit it.

let val2 = $state('');
const wrapped = $writable(val2)
doSomethingWithState(wrapped)

This gets compiled to

let val2 = $state('');
const wrapped = { 
  get value(){ return val2; }, 
  set value(newValue){ val2 = newValue }
};
doSomethingWithState(wrapped)

($readable would omit the setter)

Obviously, this is all pretty new to me, so maybe I'm missing something.

Alternatives considered

The alternative is creating the object with the getter/setter manually.

Importance

would make my life easier

@benmccann benmccann added this to the 5.x milestone Sep 21, 2023
@benmccann benmccann removed this from the 5.x milestone Sep 21, 2023
@look997
Copy link

look997 commented Sep 23, 2023

This can be hidden in $state.writable() and $state.readable(). There is $effect.pre(), so it is similar....

@aloker
Copy link

aloker commented Sep 24, 2023

As I learned, the way forward will probably be something like a helper function such as

function writable(initial){
  let value = $state(initial);
  return {
    get value() { return value; },
    set value(v) { value = v; }
  }
}

which can be implemented in user land or as a helper function shipped with Svelte. You'd lose immediate access to the value, but IMO fewer runes is better. As such, I think, this feature request is obsolete.

@WaltzingPenguin
Copy link

While you can implement it in userland, that means everyone will implement a slightly different version. For library authors, that's a big deal. If you're using multiple third party libraries, how much of a headache do you want to deal with because one used object.value, one used object.val, and the last one decided on object.$?

@aradalvand
Copy link

aradalvand commented Sep 25, 2023

As such, I think, this feature request is obsolete.

No really. This feature request is (or should be) about shipping this helper with Svelte, because it's such a commonly-needed utility, it makes sense to include it in the standard library.

@aloker
Copy link

aloker commented Sep 25, 2023

Helper functions as outlined above should be shipped with Svelte, but I'm not sure anymore (I'm the author of the issue, company account vs private account etc) that there's a need for runes for this purpose. Fewer runes means less compiler magic which is better IMO.

@stalkerg
Copy link
Contributor

stalkerg commented Sep 25, 2023

Honestly, I believe removing store and $storeVar syntax is a mistake. It seems like the core team keeps in mind only a few use cases and completely ignores others.
Runes itself is fine, but we should keep the store as is - runes and signals are not a replacement for the store for all cases.

@Rich-Harris
Copy link
Member

Perhaps you'd like to enumerate those cases?

@stalkerg
Copy link
Contributor

Yes, I will try. I hope the community also helped me.

PS Maybe it's just my common overreaction... as I remember, I argue a lot after svelte2 and after svelt3 release as well. :) Sory for that, but I feel there is something wrong.

@JakeBeaver
Copy link
Contributor

JakeBeaver commented Oct 5, 2023

I'm hoping we get a LOT of syntax sugar before runes ship. Runes did make global state a little more manageable and more fine grain for when you need it, but they effectively nuked the .svelte files (yes, you did blow it all to hell :D).

Would love to see something like https://pelte.dev/ be included out of the box.

I almost never need more than simple variables in components, so I'm dreading the day when the automatic migration to runes comes along with svelte 6+, (effectively runs pelte-ish preprocessor as a converter?), makes all reactive variable declarations double in length, and thus my codebases becomes so much less lovely and svelte.

@adminy
Copy link

adminy commented Oct 5, 2023

write the value out at the end of your function calls, this way you do all the distructive stuff at the end or all the reactive stuff outside your core logic. its even better this way as it forces you to keep your code cleaner and at the boundaries of state interactions.

@stalkerg
Copy link
Contributor

I'm hoping we get a LOT of syntax sugar before runes ship.

I am hopeful too but core developers are silent and even officially said, that it's maybe will not be part of the first release.

@stalkerg
Copy link
Contributor

I suppose $wrap like function should be part of svelte5 https://github.com/flakolefluk/dark-runes?tab=readme-ov-file#wrap-writables-readables-and-properties

@Rich-Harris
Copy link
Member

Circling back: it would be premature to add these until Svelte 5 is stable and we see what patterns emerge organically. It's easy enough to do this...

const answer = $state({ value: 42 });

...for the cases where you need this (which I honestly don't expect to be all that frequent), that introducing additional API (whether in the form of a rune or a helper) feels excessive. (That wasn't possible at the time this issue was created, since it predates #9739.)

It may well be the case that we need to pave some cowpaths in future, but the sensible thing to do for now is wait.

@stalkerg
Copy link
Contributor

Thanks, seems it's a good enough for me. Yeah, proxied state it's big improvement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

10 participants