-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Svelte 5: Bring back $state.link #13452
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
Comments
For reference: #12938 (comment) here is the decision to remove The problem was that, after correcting the behaviour, it used the Examples: sync let box = link(() => parentValue, onMerge);
console.log(box.value); |
Couldn't you just use a let a = $state(0);
let b = $derived(a); |
No, derives are read-only (though mutable). So you cannot do |
Ah, I see. let a = $state(0);
let b = $state($state.snapshot(a));
$effect(()=>{
b = $state.snapshot(a);
}); It shouldn't be too much of a problem that |
It didn't. It used a derived. We wanted to not ship something that we regretted and given how close we are to 5.0 release, we felt like doing this work after release was a better use of time. |
Initial implementation — yes, but it was buggy, and the PR I've linked was fixing it by using effect instead of derived. |
@7nik The effect wasn't the fix, it was just a bug in the initial implementation. |
Here's a workaround that avoids effects but has manual resetting, the verboseness has some clarity: value; // maybe from a prop, `type T`
let local_value: T | undefined = $state(value); // or initialize to `undefined` or something else
const final_value = $derived(local_value === undefined ? value : local_value); // `type T`
value = something; // update the source of truth
local_value = something; // update just the final linked binding
local_value = undefined; // revert the final linked binding to the source of truth This means your handlers may sometime need a 2-liner to both revert the linked binding and update the source of truth, a pattern that's been talked about in these discussions - you can have these updates in a single-code-path helper to mitigate the error-proneness. This could be wrapped in a helper API with explicit methods to improve usage. |
Regardless of what implementation is used or what issues have to be addressed, people will need this mechanism. There are too many cases where a single source of truth (for example the server) provides data which has to be mutable for editing. In one of my projects I implemented reordering elements of a list which was saved in a database using exactly this kind of functionality (a seperate variable assigned by an effect). Otherwise, I wouldn't have been able to animate the drag and drop. Since people need this feature and they shouldn't stumble into the problems of SSR and nested assignments, a seperate rune with thorough documentation would be really helpful. But maybe naming it something else should be considered, for the state is not really linked, but it rather expresses a possible future state of the data. Some funny ideas I had were I was thinking that it would also be useful to provide a mechanism for resetting the "dependent" state to the source of truth without repeating oneself. Maybe a |
I've come back to say: I find myself often using something like let arr = $derived(this.deeply.nested.array_thing) // Not reactive for setting
arr = array.filter(...) // wouldn't work So yes, having something like: let arr = $state.link(this.deeply.nested.array_thing) Would be really nice |
Theoretically, if #12956 were to be made, wouldn't that provide an easy way to recreate let arr = $state.from({
get: ()=>this.deeply.nested.array_thing,
set: v=>this.deeply.nested.array_thing=v
}); |
Addressed in #15570 |
Describe the problem
Knowing that $state.link existed once, I can't stop thinking how many times I could use it in my project. It's really useful and removes the need of having to write an extra $effect that does nothing other than assigning a value to a variable. Also the work around that uses an $effect isn't really good either because the assignment inside $effect is not fine-grained.
Describe the proposed solution
I think it would be nice to have it back and makes migrating from svelte 4 easier since in svelte 4 you could assign to the reactive variable and it would update again if its dependency changed.
For example, you could do the following in svelte 4 when you didn't want to change the original data passed by the user and still update your finalData if it got updated
So here finalData was updated internally but it would have been updated again if the user decided to update the data prop.
This could translate to the following in Svelte 5 which is neat:
Importance
nice to have
The text was updated successfully, but these errors were encountered: