Reputation: 4501
I have a piece of Svelte code that is supposed to:
Load a number from an external source when clicking on "Load" button
Save the number to an external source when the number changes
https://svelte.dev/repl/5d64d5ba6c5e4df6b12cb4c1fb3b716b?version=3.49.0
<script>
let num
let msgs = []
const inc = function() {
num += 1
}
const load = function() {
const num_ = 1
msgs = [...msgs, 'load num ' + num_]
num = num_
}
const save = function(num_) {
msgs = [...msgs, 'save num ' + num_]
}
$: save(num)
</script>
<button on:click={load}>Load</button>
<button on:click={inc}>Inc</button>
{#each msgs as msg}
<li>{msg}</li>
{/each}
My problem is that, after loading the page and clicking Load and Inc once each, I get this result:
save num undefined
load num 1
save num 1
save num 2
where I have two superfluous saves:
save num undefined
save num 1
I know I can manually track these with additional variables and what not, but is there a better way to avoid these?
Upvotes: 1
Views: 152
Reputation: 106
The reactive blocks run during the component initialization as well. This is why you get save num undefined
.
If you want just rid of this line, check the num
value:
$: if (num !== undefined) save(num);
If the num
is defined with some tricky value, and in some other cases, you need to use a flag:
let ready = false;
onMount(() => {
ready = true;
});
function save(num_) {
if (!ready) return;
// your code
}
$: save(num);
Also, just calling save
at the end of inc
and load
is a good way to control when the function is called.
Upvotes: 0
Reputation: 185140
If load/save are expensive operations (e.g. server/DB calls), they should be gated by using events or debounced updates (changes schedule an update, rather than executing them directly).
If load/save are just affecting local state, it should not matter that there are superfluous calls. Svelte updates DOM fairly selectively and its change tracking is not very expensive (compared with other mechanisms like dirty checking the whole model or virtual DOM reconciliation).
By using a blanket reactive statement there is no way to differentiate between initialization, load or user initiated mutation which causes those superfluous calls.
In general I would recommend to use reactive statements primarily for simple invariants that do not rely on the number of calls.
Upvotes: 0