sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.56k stars 4.12k forks source link

Svelte 5: Bring back $state.link #13452

Open HighFunctioningSociopathSH opened 7 hours ago

HighFunctioningSociopathSH commented 7 hours ago

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

export let data;
$: finalData = data;
function handleOnClick() {
  finalData = "something";
}

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:

let { data } = $props();
let finalData = $state.link(data);
function handleOnClick() {
  finalData = "something"
}

Importance

nice to have

7nik commented 4 hours ago

For reference: https://github.com/sveltejs/svelte/pull/12938#issuecomment-2299767265 here is the decision to remove $state.link.

The problem was that, after correcting the behaviour, it used the $effect internally anyway. Also, there were open questions about behaviour in SSR and the inability to apply $state.link to an object's prop. A workaround can have whatever behaviour you need.

Examples: sync $state.link and $state.link with async merging. If you want, you can wrap the logic into the Box pattern and have something like

let box = link(() => parentValue, onMerge);
console.log(box.value);