So I have this React component which uses the useEffect() hook:
const [stateItem, setStateItem] = useState(0);
useEffect(() => {
if (condition) {
myFunction();
}
}, [stateItem]);
const myFunction = () => {
return 'hello';
}
React gives me a warning about 'myFunction' being a missing dependency. I (think I) understand why and I've read through many similar questions asking for more or less the same thing, but the answer is always 'move your function into the useEffect hook'. This would be fine if not for myFunction being called from different places, e.g.:
...
return (
<Button onClick={() => myFunction()} />
);
therefore I cannot put my function inside the useEffect hook.
One answer to a similar question was to put the function outside the component, but that would require me to pass a lot of data to my functions, e.g.
const myFunction(stateItem, setStateItem, someProp) => { stuff };
which gets extremely tedious when there are several functions with many props, state hooks etc. to pass.
Aside from putting a linter ignore comment above the useEffect hook, is there anything more practical to do about this? I'm finding these things to make using react hooks very impractical.
I've had issues with this.
React is always trying to keep your effects up-to-date. If you don't pass a dependency array, React will run that effect after every render, just in case.
This will run on every render
useEffect(()=> {
// DO SOMETHING
});
If you pass an empty array, you're basically telling that your effect does not depend on anything, and it's safe to run it only once.
This will only run once
useEffect(()=> {
// DO SOMETHING
},[]);
If you populate the dependency array, you're telling the your effect depend on those specific things, and if any of them changes, the effect needs to be run again, otherwise, it doesn't have to.
This will only run if someProp
or someFunction
changes.
useEffect(()=> {
// DO SOMETHING
},[someProp,someFuction]);
NOTE: Remember functions, objects and arrays are compared by reference
So, basically your options are:
If you choose to add it to the array, you need to decide the following:
If that function gets modified, do you need your effect to run again?
If this is true, simply add it to the dependency array and React will take care of re-running your effect every time that function changes.
If this is not true, wrap your function into a useCallback
so you can keep its reference the same across renders. You can also add a dependency array to the useCallback
to control when the function needs to be recreated, or not.
EXTRA The function needs to be recreated, but you don't want to re-run.
useRef()
to keep track of whether the effect has run once, and write a check into your effect to stop the effect if it's has run before. Like:const effectHasRun_ref = useRef(false);
useEffect(()=>{
if (effectHasRun_ref.current === true) {
return;
}
else {
// RUN YOUR EFFECT
effectHasRun_ref.current = true;
}
},[yourFunction]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With