In a project with React components using hooks, I am trying to understand how to properly avoid calling callbacks that are bound to old state values. The below example illus
You should useCallback
and pass it as a dependency to your effect.
const doStuff = useCallback(() => {
console.log(message);
}, [message]);
useEffect(() => {
const interval = setInterval(doStuff, 1000);
return () => clearInterval(interval); // clean up
}, [doStuff]);
Here when message
gets updated it will have its new value in the doStuff
You can put this in it's own hook also. I have this in my production code
/**
* A react hook for setting up an interval
* @param handler - Function to execute on interval
* @param interval - interval in milliseconds
* @param runImmediate - If the function is executed immediately
*/
export const useInterval = (handler: THandlerFn, interval: number | null, runImmediate = false): void => {
const callbackFn = useRef<THandlerFn>()
// Update callback function
useEffect((): void => {
callbackFn.current = handler
}, [handler])
// Setup interval
useEffect((): (() => void) | void => {
const tick = (): void => {
callbackFn.current && callbackFn.current()
}
let timerId: number
if (interval) {
if (runImmediate) {
setTimeout(tick, 0)
}
timerId = setInterval(tick, interval)
return (): void => {
clearInterval(timerId)
}
}
}, [interval, runImmediate])
}