I'm using @preact/signals-react along with the babel transformer and am running into an issue with React's useEffect. The official react lint rule react-hooks/exhaustive-deps doesn't play nicely with signals.
Consider this example:
import { signal } from '@preact/signals-react';
const countSignal = signal(0);
export function Counter({ multiplier: number }) {
useEffect(() => {
localStorage.setItem('countWithMultiplier', `${multiplier * countSignal.value}`);
}, [multiple, countSignal.value]);
return (<div>
{multiplier * countSignal.value}
<button onClick={() => countSignal.value++}>Add One</button>
</div>);
}
The above will fail the react-hooks/exhaustive-deps check because countSignal.value in the list of useEffect dependencies is declared an error:
Outer scope values like 'countSignal.value' aren't valid dependencies because mutating them doesn't re-render the component
I know that there exists a useSignalEffect hook to allow a component to run side effects on a signal's change, but it's only for signals, it can't trigger on prop changes too (like in the example).
This can be worked around by assigning the value to a local variable first (const countValue = countSignal.value), but that's annoying. Plus before you even remember to do that, an eslint autofix would just silently remove the countSignal.value dependency from useEffect, leading to a potential bug.
One potential fix could be to add an optional dependency array to useSignalEffect so that it can also trigger on non-signal changes. Also, useSignalEffect isn't documented, so there's that too.
Update: Fixed example, now using a signal created out of scope of the component to reflect the actual case were the linter raises a warning.
I'm using
@preact/signals-reactalong with the babel transformer and am running into an issue with React'suseEffect. The official react lint rulereact-hooks/exhaustive-depsdoesn't play nicely with signals.Consider this example:
The above will fail the
react-hooks/exhaustive-depscheck becausecountSignal.valuein the list of useEffect dependencies is declared an error:I know that there exists a
useSignalEffecthook to allow a component to run side effects on a signal's change, but it's only for signals, it can't trigger on prop changes too (like in the example).This can be worked around by assigning the value to a local variable first (
const countValue = countSignal.value), but that's annoying. Plus before you even remember to do that, an eslint autofix would just silently remove thecountSignal.valuedependency from useEffect, leading to a potential bug.One potential fix could be to add an optional dependency array to
useSignalEffectso that it can also trigger on non-signal changes. Also,useSignalEffectisn't documented, so there's that too.Update: Fixed example, now using a signal created out of scope of the component to reflect the actual case were the linter raises a warning.