Svelte 52: Performance — {#key} Blocks & $state.raw
easy⏱ 5 mincoursesvelte
{#key} forces a remount, not just an update
Normally Svelte patches the DOM in place and preserves component state across re-renders. Wrapping content in {#key expression} changes that: whenever expression's value changes (by ===), Svelte destroys the old instance and creates a brand new one — its $state resets to initial values and any entrance transition replays.
{#key selectedUserId}
<UserAvatar id={selectedUserId} />
{/key}
<!-- UserAvatar's own internal $state (e.g. a hover/animation flag)
resets every time selectedUserId changes, since it's a fresh instance. -->
$state.raw: opt out of deep reactivity
let obj = $state({...}) deeply proxies obj, so mutating obj.nested.value triggers updates. let obj = $state.raw({...}) does NOT proxy nested data — mutating a property silently does nothing to the UI. Only obj = {...newValue} (a full reassignment) notifies subscribers. This avoids the cost of deep-proxying large structures you rarely mutate.
let big = $state.raw({ rows: hugeArray });
big.rows.push(newRow); // silently ignored by reactivity — UI won't update
big = { ...big, rows: [...big.rows, newRow] }; // triggers update
Watch the raw stat lag, then jump
In the demo, click 'Mutate in place' a few times — the deep $state row updates instantly, but the raw row looks frozen. It ISN'T frozen: the object is being mutated the whole time. Click 'Reassign raw' once and the raw row snaps to the true accumulated value — proof that raw data was changing invisibly to Svelte until a reassignment made it visible.