React useRequestAnimationFrame hook
Runs an animating function, calling it before every repaint.
- Use the
useRef()
hook to create two variables.requestRef
will hold the last request id andpreviousTimeRef
will hold the last timestamp. - Define a function,
animate
, which handles updating these variables, runs thecallback
and callsWindow.requestAnimationFrame()
perpetually. - Use the
useEffect()
hook with an empty array to initialize the value ofrequestRef
usingWindow.requestAnimationFrame()
. Use the returned value andWindow.cancelAnimationFrame()
to clean up when the component unmounts.
const useRequestAnimationFrame = callback => { const requestRef = React.useRef(); const previousTimeRef = React.useRef(); const animate = time => { if (previousTimeRef.current) callback(time - previousTimeRef.current); previousTimeRef.current = time; requestRef.current = requestAnimationFrame(animate); }; React.useEffect(() => { requestRef.current = requestAnimationFrame(animate); return () => cancelAnimationFrame(requestRef.current); }, []); }; const Counter = () => { const [count, setCount] = React.useState(0); useRequestAnimationFrame(deltaTime => { setCount(prevCount => (prevCount + deltaTime * 0.01) % 100); }); return <p>{Math.round(count)}</p>; }; ReactDOM.createRoot(document.getElementById('root')).render( <Counter /> );