Skip to content

Instantly share code, notes, and snippets.

@dbabbs
Last active December 7, 2020 18:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dbabbs/3f843443ec14dd9ec6a4625fa17e8ca2 to your computer and use it in GitHub Desktop.
Save dbabbs/3f843443ec14dd9ec6a4625fa17e8ca2 to your computer and use it in GitHub Desktop.
React hook for requestAnimation Frame
/* Usage:
import { useState } from 'react';
import useAnimationFrame from '../../hooks/useAnimationFrame';
const [animationActive, setAnimationActive] = useState(true);
useAnimationFrame(() => {
//perform action here
}, animationActive);
*/
import { useRef, useEffect, useCallback } from 'react';
function useAnimationFrame(exec, active) {
const savedExec = useRef();
const interval = useRef();
useEffect(() => {
savedExec.current = exec;
}, [exec]);
const step = useCallback(() => {
savedExec.current();
if (interval.current) {
requestAnimationFrame(step);
}
});
const cancel = useCallback(() => {
cancelAnimationFrame(interval.current);
interval.current = null;
});
useEffect(() => {
if (active) {
interval.current = requestAnimationFrame(step);
}
return () => cancel();
}, [active]);
}
export default useAnimationFrame;
@behnammodi
Copy link

behnammodi commented Dec 7, 2020

Every animation function needs to know the elapsed time to determine the progress of the animation. so:

import { useRef, useEffect, useCallback } from 'react';
function useAnimationFrame(exec, active) {
   const savedExec = useRef();
   const interval = useRef();
   useEffect(() => {
      savedExec.current = exec;
   }, [exec]);

   const step = useCallback((timestamp) => {
      savedExec.current(timestamp);
      if (interval.current) {
         requestAnimationFrame(step);
      }
   });

   const cancel = useCallback(() => {
      cancelAnimationFrame(interval.current);
      interval.current = null;
   });

   useEffect(() => {
      if (active) {
         interval.current = requestAnimationFrame(step);
      }
      return () => cancel();
   }, [active]);
}

export default useAnimationFrame;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment