Regarding reactive declarations in svelte like
$: doubled = count*2
, it states in the svelte tutorial that
Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'
The conventional javascript feature refrences seems to be labels (please confirm)
Please explain how this is done by the svelte compiler in simple words and provide a reference to the place in the compiler code where this happens [or starts to happen]
There is a githb issue open to explain svelte internals eventually.
Under-the-hood, Svelte keeps the DOM in sync with the application state and updates the value of the component whenever the value of the variable changes. Generally, for assigned variables, you do not need any additional setup to make them reactive.
At the heart of Svelte is a powerful system of reactivity for keeping the DOM in sync with your application state — for example, in response to an event. Svelte 'instruments' this assignment with some code that tells it the DOM will need to be updated.
Svelte's reactivity not only keeps the DOM in sync with your application's variables as shown in the previous section, it can also keep variables in sync with each other using reactive declarations.
$$props references all props that are passed to a component, including ones that are not declared with export . It is not generally recommended, as it is difficult for Svelte to optimise. But it can be useful in rare cases – for example, when you don't know at compile time what props might be passed to a component.
In Svelte, there's a special way to do this. Instead of declaring a variable with let, we will use $:. This is a labeled statement (it's valid JS), and it's used by the compiler to let it know that a reactive variable is being declared, and it depends on all the variables that are added to the expression. In our example:
The change is also rendered in the {bookCount}. In other words, Svelte will make sure that if the value of a variable changes in our script code, the same should be reflected in the DOM. Note that Svelte’s reactivity triggers only at the time of assignment using = operator.
In other words, Svelte will make sure that if the value of a variable changes in our script code, the same should be reflected in the DOM. Note that Svelte’s reactivity triggers only at the time of assignment using = operator.
Don't worry if this looks a little alien. It's valid (if unconventional) JavaScript, which Svelte interprets to mean 're-run this code whenever any of the referenced values change'. Once you get used to it, there's no going back.
It is indeed the label syntax.
Javascript labels are seeing little to no use, so it was an elegant way to make create a simple syntax as well making sure it would play nice with linters and IDEs.
Where can you find the code :
Once the code is compiled, you can find the reactive declarations in the state update part of the component lifecycle. However this code is not executed between the beforeUpdate and afterUpdate which are related to the DOM update. If you change values in those callbacks, you might get some wacky results as the reactive statements may not be updated.
You can find it in the code if you look for $$self.$$.update
.
How it works :
The compiler is analyzing those statements to find which variables to observe for changes. Those variables being everything right of the assignment operator, or every argument in a function call. It is worth noting that const variables are not observed as they are never supposed to change.
$: doubled = count * 2;
will compile to
if ($$dirty.count) { $$invalidate('doubled', doubled = count * 2); }
$$dirty is the argument received by the update lifecycle, it is an object containing properties for each variables potentially modified, that are set to 1 when $$invalidate
is called on it.
Svelte then add thoses statements at the end of the update part of the lifecycle, and condition their execution on the changes of at least one of the aforementioned observed variables.
Svelte is also ordering those statements in a topological order. This means that a reactive statement making use of another reactive statement results is going to be evaluated after. Regardless in which order you put them in your code.
$: quadrupled = doubled * 2;
$: doubled = count * 2;
will still correctly compile to
if ($$dirty.count) { $$invalidate('doubled', doubled = count * 2); }
if ($$dirty.doubled) { $$invalidate('quadrupled', quadrupled = doubled * 2); }
Hope it helps clear things up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With