We outline some common gotchas or un-intuitative bahaviour in svelte
In svelte 4, you had to do this.
<script>
let arr = [0, 1]
function handleClick() {
arr.push(2)
arr = arr // [!code highlight]
}
</script> https://v4.svelte.dev/docs/svelte-components#script-2-assignments-are-reactive
It was unintuitive that you had to reassign arrays and objects to trigger reactivity. Svelte 5 also has its own set of unintuitive patterns. Here, I will attempt to document them.
# Destructuring can break reactivity
Either use data.foo or add a $derived rune.
<script>
let { data } = $props()
const { foo } = data // [!code --]
const { foo } = $derived(data) // [!code ++]
</script>
{foo} In JavaScript, destructured declarations are evaluated at the time of destructuring. src: https://github.com/sveltejs/svelte/issues/11911#issuecomment-2195478261
# Intermediate variables can break reactivity
Either use data.foo or add a $derived rune.
todo: seperate intermediate and destructure
<script>
let { data } = $props()
const foo = data.foo // [!code --]
const foo = $derived(data.foo) // [!code ++]
</script>
{foo} # data in $state will not receive upstream updates
<script>
let { data } = $props()
const foo = $state(data.foo) // [!code --]
const foo = $derived(data.foo) // [!code ++]
</script>
{foo} # Module exports are immutable
$state should be used with an object so it can be mutated.
//util.svelte.js
export const value = $state(5) // [!code --]
export const value = $state({ current: 5 }) // [!code ++] # Direct DOM maniputation will desync the Svelte’s runtime
Let svelte change the DOM
<script>
let value = $state(0)
</script>
<button onclick={(e) => (e.currentTarget.innerHTML = 4)}>{value}</button> // [!code --]
<button onclick={(e) => (value = 4)}>{value}</button> // [!code ++] # Avoid using browser globals
<script>
const input = document.getElementById('id') // [!code --]
let input // [!code ++]
</script>
<input id="id" /> // [!code --]
<input bind:this={input} /> // [!code ++] <script>
const handler = () => console.log('Boo!')
const input = document.getElementById('button') // [!code --]
button.addEventListener('click', handler) // [!code --]
</script>
<button id="button">click to see</button> // [!code --]
<button onclick={handler}>click to see<button> // [!code ++] <script>
const onresize = () => console.log('Window resized!')
window.addEventListener('resize', onresize) // [!code --]
</script>
<svelte:window {onresize} /> // [!code ++]