useFps
Description and use case
useFps measures frame deltas with requestAnimationFrame and exposes a rolling FPS average. Use it to disable expensive animations, canvas effects, video backgrounds, or other non-essential UI when the browser falls below your target frame rate.
API signature
function useFps(options?: UseFpsOptions): UseFpsReturn;
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
options.threshold | number | No | FPS threshold used to set isLowPerformance. Defaults to 30. |
options.windowSize | number | No | Number of recent frame deltas used for the moving average. Defaults to 10. |
options.onDrop | (currentFps: number) => void | No | Callback fired when the rolling average crosses below threshold. |
options.enabled | boolean | No | Set false to disable the rAF loop. |
Return value
| Field | Type | Description |
|---|---|---|
fps | number | Rolling-averaged FPS. Returns 0 until the first measured frame. |
isLowPerformance | boolean | Whether fps is below the configured threshold. |
isSupported | boolean | Whether this browser supports requestAnimationFrame and cancelAnimationFrame. |
Live interactive demo (StackBlitz)
GitHub Pages does not serve the isolation headers required for embedded StackBlitz WebContainers. Open the demo in StackBlitz to run it interactively.
Code example
import { useFps } from 'react-perf-hooks';
export function AdaptiveMedia() {
const { fps, isLowPerformance, isSupported } = useFps({
threshold: 30,
windowSize: 10,
onDrop: (currentFps) => {
navigator.sendBeacon('/analytics/fps-drop', JSON.stringify({ currentFps }));
},
});
if (!isSupported) {
return <StaticImage />;
}
return (
<section>
<p>FPS: {fps.toFixed(0)}</p>
{isLowPerformance ? <StaticImage /> : <HeavyLottieAnimation />}
</section>
);
}
Notes
onDropfires on transitions into low-performance mode, not on every low-FPS frame.- Background-tab rAF pauses are excluded from the rolling average.
- The hook cancels the active animation frame loop when the component unmounts.