useRequestAnimationFrame

React, Hooks, Effect

Runs an animating function, calling it before every repaint.

  • Use the useRef() hook to create two variables. requestRef will hold the last request id and previousTimeRef will hold the last timestamp.
  • Define a function, animate, which handles updating these variables, runs the callback and calls Window.requestAnimationFrame() perpetually.
  • Use the useEffect() hook with an empty array to initialize the value of requestRef using Window.requestAnimationFrame(). Use the return value and Window.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.render(<Counter />, document.getElementById('root'));

Recommended snippets

  • Executes a callback immediately before a component is unmounted and destroyed.

  • useEffectOnce

    React, Hooks

    Runs a callback at most once when a condition becomes true.

  • usePersistedState

    React, Hooks

    Returns a stateful value, persisted in localStorage, and a function to update it.