A hook to effortlessly run requestAnimationFrame()
in React (demo):
import useAnimationFrame from 'use-animation-frame';
const Counter = () => {
const [time, setTime] = useState(0);
useAnimationFrame(e => setTime(e.time), []);
return <div>Running for:<br/>{time.toFixed(1)}s</div>;
};
Inspired by CSS-Tricks' Using requestAnimationFrame with React Hooks and my twitter reply.
Accepts first a function and second a dependency list similar to useEffect()
:
useAnimationFrame(callback, dependencies);
The callback will be called on each requestAnimationFrame. Also it's very likely that you want to provide dependencies or [] if there's none to avoid infinite loops and unnecessary re-renders.
The callback accepts a single parameter, which is an object with two properties (based on the performance.now()
API):
time
: the absolute time since the hook was first mounted. This is useful for wall clock, general time, etc.delta
: the time since the hook was run last. This is useful to measure e.g. FPS.
All times are in the International System of Units seconds, including decimals.
With my other library use-interpolation it's easy to calculate the FPS (see in CodeSandbox):
import React, { useState } from "react";
import useInterpolation from 'use-interpolation';
import useAnimationFrame from 'use-animation-frame';
const Counter = () => {
const [time, setTime] = useState(0);
// 1s of interpolation time
const [fps, setFps] = useInterpolation(1000);
useAnimationFrame(e => {
setFps(1 / e.delta);
setTime(e.time);
}, []);
return (
<div>
{time.toFixed(1)}s
<br />
{fps && Math.floor(fps.value)} FPS
</div>
);
};