Description
Describe the bug
Setting up client global state is a footgun. (see #4339). Almost 3 years and users are still confused about how to do it safely. I want to add this pattern to the docs. This should also help clear up confusion around server shared state.
On top of that, it resolves optimistic UI issues mentioned in #12999.
To summarize, this pattern provides a state that can be updated from the server and the client, is in sync across child components, has type safety and is safe from data leaks.
// ReactiveState.svelte.js
export class ReactiveState {
value = $state();
constructor(initialValue) {
this.value = initialValue
}
}
// routes/+layout.js
export const load = () => {
const randomNumber = Math.floor( Math.random() * 11)
return { state: new ReactiveState(randomNumber) }
}
<script>
// +page.svelte
let { data } = $props()
</script>
{data.state.value}
<button onclick={() => { data.state.value++ }}>add one</button>
repl: https://www.sveltelab.dev/90t6s7u8l5svxn0
Alternatives
There is an alternative which involves defining your own context.
https://discord.com/channels/457912077277855764/1303014718268637264
https://discord.com/channels/457912077277855764/1303116841895333918
https://discord.com/channels/457912077277855764/1301456686963359795
Severity
annoyance
Additional Information
Prior discussions
https://discord.com/channels/457912077277855764/1305894527738974258
Use cases
websocket updates
https://discord.com/channels/457912077277855764/1306898519184904235
persistent state across pages
https://discord.com/channels/457912077277855764/1307335664743747614
https://discord.com/channels/457912077277855764/1313490960524775435
when is it safe to use global state
https://discord.com/channels/457912077277855764/1313289238762225694
https://discord.com/channels/457912077277855764/1316016073576812554