Component in svelte 4:
<script>
let x = 1
let y = "less than 10"
function check(){
if(x > 10){
y = "more than 10"
}
}
$: {
check()
}
</script>
<div>
not runes
<button onclick={() => x++ }>{x}</button>
{y}
</div>
Notice how the reactive statement calls a check function, so the reactive statement is never triggered because "x" is not directly called.
But in runes mode the $effect
is triggered even if "x" does not directly appear in the effect body:
<script>
let x = $state(1);
let y = $state("less than 10");
function check(){
if(x > 10){
y = "more than 10"
}
}
$effect(() => {
check()
})
</script>
<div>
runes
<button onclick={() => x++ }>{x}</button>
{y}
</div>
I guess this is change in how svelte effects work from 4 to 5, but I was wondering how does svelte know when to run the effect, when in runes mode? Does it look into the function code and check of reactive vars? What if I have a deeply nested function call, with a reactive var in the deepest function, will the effect still detect it?
Does it look into the function code and check of reactive vars?
This works via signals which communicate via a shared context at runtime.
You can think of it as an effect setting up a global list and each signal (some kind of state) adding itself to this list of dependencies when accessed. At the end of the effect execution, the list will contain all things whose changes should trigger the effect again.
What if I have a deeply nested function call, with a reactive var in the deepest function, will the effect still detect it?
Yes, as long as no async code breaks up the execution.
(Svelte 3/4 uses compile time code analysis which cannot do this.)