Optimize Svelte’s Reactive Statements
The $: dollar sign is magical, at least with numbers and strings
Svelte’s reactive declarations and statements are amazing. It automatically *reacts* to depending variables. Values are updated, statements are re-ran, and every depending UI is synced accordingly. It is definitely a great DX.
Behind all this magic is diffing. Svelte has to check and decide if depending variables have changed. This is easy for strings and numbers. The official Svelte tutorial uses a number variable count
. However, this is not the case with objects. Passing object to a function should be executed carefully.
Check this REPL. Everytime the button is pressed, the obj
gets updated. obj.now
stays the same, but the obj
is changed. Therefore, $: fn(obj);
runs every time the button is pressed. However, $: fn(objNow);
does not.
To create a reactive statement that runs only when an object’s specific value has changed, create another reactive declaration that extracts this value.
// ✅
$: objNow = obj.now; // Runs everytime `obj` changes
$: fn(objNow); // Only runs when `objNow` number changes
// ❎
$: fn(obj.now);
$: fn(obj);
Svelte basically does useMemo-like optimization for you, but sometimes the dependencies should be explicitly declared. For example, passing a String.match() result, which is an array, to a reactive statement should be double checked. Especially, if it can cause expensive computations.