-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Description
Describe the bug
- Reactive updates for local state changes are broken post-migration.
- The migration tool does not address or mention this behavioural change.
$effectis discouraged, yet it is the only viable solution for handling updates that come from both the client and server. This is neither mentioned nor explained in the migration or core documentation.
Suggestions
- The migration CLI should flag this change and recommend solutions.
- Clarify when the use of
$effectis appropriate
Step 1 - Svelte 4 Reactivity
<script>
export let data
</script>
{data.value}
<button on:click={() => { data.value++ }}>add one</button>This is a typical reactive setup with local state update for optimistic UI.
Step 2 - Migrate to svelte 5 via npx sv migrate svelte-5
<script>
let { data = $bindable() } = $props()
</script>
{data.value}
<button onclick={() => { data.value++ }}>add one</button>The CLI replaced export let with $props, but we're no longer able to get reactive updates for data.value. $bindable() was also added for no observable effect.
Step 3 - Use $state
<script>
let { data = $bindable() } = $props()
let value = $state(data.value)
</script>
{value}
<button onclick={() => { value++ }}>add one</button>Local updates now work, but we're no longer able to receive updates from the server.
Step 3.1 - Use $derived
<script>
let { data = $bindable() } = $props()
let value = $derived(data.value)
</script>
{value}
<!-- <button onclick={() => { value++ }}>add one</button> -->Cannot assign to derived state. :|
Step 3.2 - Use $state + $effect
<script>
let { data = $bindable() } = $props()
let value = $state(data.value)
$effect(() => {
value = data.value;
});
</script>
{value}
<button onclick={() => { value++ }}>add one</button>Finally, we're able to return to the svelte 4 behaviour. This is also the solution @benmccann suggests in sveltejs/svelte#14536. But this solution is a problem, as he puts it.
why are we encouraging this? it seems so gross and feels like anti-pattern
source
On top of that step 3 and 3.1 were intuitive solutions a user will reach for, yet it is incorrect.
Severity
blocking an upgrade
Additional Information
Global State
I think there is also a high correlation between this and setting up a global state, as users often will and are encouraged to set up their data in the load fn and would like to use them in various pages. I created a second issue that addresses that in #13000.
Related discussions from maintainers
- Svelte 5: can't link reactivity from
$props()svelte#14536 - https://discord.com/channels/457912077277855764/1303297143276179467
- Svelte 5: Bring back $state.link svelte#13452