State Values
The concept of state is related to dynamic values, and it is an additional way to work with template values that you expect to change and that the template should react to.
const [count, setCount] = state(0);
const countUp = () => {
setCount(prev => prev + 1)
}
const counter = html`
<p>${count}</p>
<button type="button" onclick="${countUp}">+</button>
`;
counter.render(document.body)
state
State is a core API much like html
and unlike any
state concept you might have heard of out there. It is part of
the template system rather than some specific utility to manage
state.
You create a state by calling the state
function
and providing it with an initial value.
state(0);
You can also provide an optional StateSubscriber
as
second argument if you want to react to the state update to
perform some side effects for example.
state<number>(0, () => {
// perform something after this state changes
});
The state
call returns an array of 3 functions:
- StateGetter: a function (dynamic value) that returns the latest value
- StateSetter: a function to update the value that can be called with the new value, or a function that takes the current value and returns a new one.
-
StateUnSubscriber: a function to
unsubscribe from the state if you provided a
StateSubscriber
to thestate
call.
const [count, setCount, unsubscribeFromCount] = state(0, () => {
// perform something after this state changes
});
As mentioned, StateSetter
can either take a new
value, or a callback that gets called with current value and
must return an updated one.
setCount(count() + 1)
setCount(prev => prev + 1)
How does state works?
The state is simply an observable the html
template
can subscribe to. This means that the template will know exactly
what state changed and where in the template that state was used
to update exactly the part of the DOM that depends on that data.
It provides an optimal way to react to dynamic value changes in comparison to the update function.
You can choose to render the state only once or keep it live, all depending on how you render it.
const [count, setCount] = state(0);
html`
<!-- Will render once and not react to changes -->
${() => count()}
${count()}
<!-- Will render and react to changes -->
${count}
${someHelper(count)}
`
To keep the state live, just “pass” it to the template as value
or to a helper that takes
StateGetter
as argument. By default, all Markup
helpers take StateGetter
as argument.
effect
The effect
helper was introduced for cases where
you have places in the template that depends on a specific
state, but you are doing some
side effect calculation with that state.
const counter = html`
<p>${count}</p>
<p>${effect(count, () => count() * 2)}</p>
`;
Simply wrap a state or dynamic value in effect
and
comma separate all the states it depends on before your "side
effect".
effect(...STATE, SIDE_EFFECT_ACTION_OR_STATE)
The effect
is simply a type of
Helper
and you can learn more about
helpers in the next section.