Reputation: 148
In the below sandbox project, I was trying to use a custom hook to attach event listener.
In the useEventListener.js file, If I pass the savedHandler.current function directly to the event listener (line no: 21) I do not get the updated state value during state update. Only when I use the savedHandler.current function inside an anonymous function(line no: 19) I am getting the updated state value.
Could someone help me understand how this works ? Is this because of this reference?
https://codesandbox.io/s/gracious-cloud-kjw7dk?file=/src/useEventListener.js
Thanks
Upvotes: 2
Views: 1175
Reputation: 1021
This is the best I can explain:
For the context, when you click the toggle flag button, only your first useEffect(callback,[handler])
runs after EVERY rendering and your second useEffect(callback,[eventName,element])
runs ONLY ONCE after the initial rendering.
useCallback
as it is and hence on every event, the same function is being called due to reasons: The event is registered only ONCE and the cleanup function does not run since the useEffect
runs only once after the initial rendering(the cleanup function will run in instances, just before the next side effect due to dependency changes, and when the component unmount). So you are registering the event only once with a memoized callback which persist across renderings. The update of savedHandler.current in the first useEffect
doesn't update the callback passed to event listener in the second useEffect
since it doesn't re-run and hence doesn't update the callback passed to the event listener.This is it. To confirm for yourself, try to add handler as the dependency on your second useEffect
as well, and pass savedHandler.current directly to the event listener. You will get the updated state value as the useEffect
now runs after every update of handler and the event listener gets the latest callback to invoke upon.
And instead of creating another variable, you can directly do element.addEventListener(eventName, (event) => savedHandler.current(event));
Upvotes: 2