Effects
Create Effects​
Effects are functions that are executed when a signal changes. You can use
useEffect()
to create an effect:
import { useSignal, useEffect } from "sinho";
const [value, setValue] = useSignal(0);
useEffect(() => {
console.log(value());
});
Inside of components, the function is first called when the component mounts, otherwise it is called immediately on creation.
The effect can track all its accessed signals and will be re-executed whenever
one of them changes, in this case value
.
Manage Dependencies​
You can also specify dependencies manually by specifying an array of
dependencies as the second argument of useEffect
:
const [name, setName] = useSignal("Jane");
const [gender, setGender] = useSignal("female");
useEffect(() => {
console.log(name(), gender());
}, [name]);
In this example, the effect will only be re-executed when name
changes. You
can also use signal.peek()
to access the value of a signal without tracking,
so the sample above is equivalent to:
useEffect(() => {
console.log(name(), gender.peek());
});
Clean Up Effects​
It is possible to return a cleanup function that will be run when the effect is re-executed or destroyed:
useEffect(() => {
console.log("Hello ", name());
return () => {
console.log("Goodbye ", name());
};
});
In this case, whenever name
is about to change, the cleanup function will be
executed first.
Batching Updates​
Say, we have an effect which depends on multiple signals:
const [name, setName] = useSignal("Jane");
const [gender, setGender] = useSignal("female");
useEffect(() => {
console.log(name(), gender());
});
If both signals change independently, the effect will be executed twice:
setName("John");
// Effect will print "John female"
setGender("male");
// Effect will print "John male"
To avoid this, you can batch updates using useBatch
:
import { useBatch } from "sinho";
useBatch(() => {
setName("John");
setGender("male");
});
// Effect will print "John male"
This way, the effect will only be executed once after all signals have changed.
In fact, all updates to signals inside of effects and event listeners will be batched by default. This is to prevent unnecessary re-renders and to improve performance, but also to ensure that all signals are in a consistent state when the effect is executed.
To manually ensure the effects are executed immediately inside an effect or
event listener, you can also use flushBatch
:
import { useEffect, flushBatch } from "sinho";
useEffect(() => {
setName("Charlie");
setGender("nonbinary");
flushBatch();
console.log(name(), gender()); // Prints "Charlie nonbinary"
});