Why is my entire component being re-rendered, even though I’m using the new “signals” library? What am I doing wrong? Only the button is supposed to be re-rendered, not the entire component.
NOTE: I used the Preact Developer Tools to test the component with the option “Highlight updates” activated. This shows the parts of the component that is being re-rendered.
Here’s the code:
import { useSignal } from "@preact/signals";
export function Home() {
const toggle = useSignal(false);
return (
<div>
<button onClick={() => (toggle.value = !toggle.value)}>
{toggle.value ? "yes" : "no"}
</button>
<p>This is re-rendered every time 'toggle.value' changes.</p>
</div>
);
}
To take advantage of the rendering optimizations, you need to use the signal directly in your component; unwrapping with .value
disables this. Docs
If you want to display different text based upon the signal value, your best bet would be to add a computed
in:
import { useSignal, useComputed } from "@preact/signals";
export function Home() {
const toggle = useSignal(false);
const toggled = useComputed(() => (toggle.value ? "yes" : "no"));
return (
<div>
<button onClick={() => (toggle.value = !toggle.value)}>
{toggled}
</button>
<p>This is re-rendered every time 'toggle.value' changes.</p>
</div>
);
}
Note: it’s generally better to use the non-hook functions (signal
and computed
vs useSignal
and useComputed
) if at all possible.