I want to be sure that when
showComponentProp
is updated, that the firstuseEffect
updates the state before the second useEffect is run.
The first useEffect
hook's callback will certainly enqueue the isVisible
state update before the second useEffect
hook is called.
I understand that
useEffect
hooks are run in the order they appear in the component body, however, as these contain setState functions, I'm not 100% sure of the behaviour. I don't want there to be a race condition between the two setState functions in theuseEffect
hooks.
All React hooks are called each render cycle, in the order they are defined. If showComponentProp
changes, then because it is included in the dependency array of both useEffect
hooks it will trigger the both useEffect
hooks' callbacks, in the order they are defined.
Could someone please clarify the exact order of the useEffects being called and when the component is rerendered in this case. For instance, is the first effect called, and when the
isVisible
state is updated, does the component rerender before the second effect is called? In that case will both effects be run again after the rerender, or just the second effect as the first effect was called previously.
useEffect
hook callbacks will be called, in order.
isVisible
state update to update to the current showComponentProp
value.showComponentProp
and timerProp
values, and if both are truthy enter the if-block and instantiate the timeout to enqueue another isVisible
state update to false, and return a useEffect
hook cleanup function.timerProp
ms and calls the callback to enqueue another isVisible
state update to false, and trigger another component rerender, e.g. back to step 1 above.In any case, both useEffect
hooks will be called each and every render cycle, and the callbacks called only when the dependencies change.
However, I suspect you could accomplish this all in a single useEffect
hook, which may make understanding the logic and flow a bit easier.
const [isVisible, setIsVisible] = useState(showComponentProp);
// Run effect when either showComponentProp or timerProp update
useEffect(() => {
// Only instantiate timeout when we've both truthy
// showComponentProp and timerProp values
if (showComponentProp && timerProp) {
// Enqueue isVisible state update "now"
setIsVisible(true);
// Enqueue timeout to enqueue isVisible state update "later"
const timeout = setTimeout(() => setIsVisible(false), timerProp);
return () => clearTimeout(timeout);
}
}, [showComponentProp, timerProp]);