Intro to Reactivity
The reactivity system is extremely simple, but it can take some time to get to know it.
At a basic level, if you call use
and pass in a property that belongs in a stateful context, it gives back a dynamic reference that will update automatically as the data updates.
The value of this
inside a functional component is always stateful, letting this example from earlier work
function App() {
this.counter = 0;
return html`
<div>
<button on:click=${() => this.counter++}>Click me!</button>
<p>${use(this.counter)}</p>
</div>
`;
}
function App() {
this.counter = 0;
return (
<div>
<button on:click={() => this.counter++}>Click me!</button>
<p>{use(this.counter)}</p>
</div>
);
}
const App: Component<{},{
counter: number
}> = function () {
this.counter = 0;
return (
<div>
<button on:click={() => this.counter++}>Click me!</button>
<p>{use(this.counter)}</p>
</div>
);
}
In this example, whenever counter
is updated, either from inside the component, from a parent component, or from devtools, the specific elements that depend on the value precisely update to reflect the new value with minimal overhead.
You can also manually create a stateful object, which is useful for nesting.
let state = $state({
a: 0,
b: $state({
c: 1,
}),
});
let elm = (
<div>
{" "}
a is {use(state.a)}, c is {use(state.b.c)}
</div>
);
document.body.appendChild(elm);
state.a++;
state.b.c++;
// div will now show "a is 1, c is 2"
Computed values
It’s important to remember that use
yields a reference pointer, not the actual value. As such, something like this will not work
<div>
<button on:click={() => this.counter++}>Click me!</button>
{use(this.counter % 2 == 0 ? "Count Is Even" : "Count Is Odd")}
</div>
As the function is only executed once ever. To have additional logic tied to state changes, you can pass in a closure to the second argument of use.
<div>
<button on:click={() => this.counter++}>Click me!</button>
{use(this.counter, (count) => (count % 2 == 0 ? "Count Is Even" : "Count Is Odd"))}
</div>
This will have the expected behavior, flipping between even and odd when the button is pressed. Remember that the “count % 2 == 0” operation is recalculated every time count
changes, but nothing else in the function is rerun.