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

The data prop in +page.svelte and +layout.svelte is no longer reactive after migrating to svelte 5 #12999

Closed
sacrosanctic opened this issue Nov 14, 2024 · 3 comments
Labels

Comments

@sacrosanctic
Copy link
Contributor

sacrosanctic commented Nov 14, 2024

Describe the bug

  • Reactive updates for local state changes are broken post-migration.
  • The migration tool does not address or mention this behavioural change.
  • $effect is 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 $effect is appropriate

Step 1 - Svelte 4 Reactivity

<script>
	export let data
</script>

{data.value}

<button	on:click={() => { data.value++ }}>add one</button>

repl: https://www.sveltelab.dev/zbbk7q85vpwanc2

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>

repl: https://www.sveltelab.dev/98hgsqyo40rxg8f

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>

repl: https://www.sveltelab.dev/4mxyw4ufpb7xd46

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> -->

repl: https://www.sveltelab.dev/ccquv598riknpuu

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>

repl: https://www.sveltelab.dev/pj3m9zhjahswqk2

Finally, we're able to return to the svelte 4 behaviour. This is also the solution @benmccann suggests in #12902 (comment). 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

Related help threads

@PatrickG
Copy link
Member

PatrickG commented Nov 15, 2024

I guess this could be fixed when Sveltekit would use $state() for the data prop.
Until then, I think I found a good solution for this.

// +page.svelte
let props = $props();

let data = $derived.by(() => {
  let state = $state(props.data);
  return state;
});

@henrykrinkle01
Copy link

While this works, it's still not intuitive, not documented and migration still breaks apps

@eltigerchino
Copy link
Member

closing as duplicate of #12902

@eltigerchino eltigerchino closed this as not planned Won't fix, can't repro, duplicate, stale Nov 19, 2024
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

4 participants