useRafFn
Call function on every requestAnimationFrame. With controls of pausing and resuming
useRafFn schedules a callback to run on every requestAnimationFrame tick, providing a high-resolution timestamp to the callback on each frame. It returns a tuple of [stop, start, isActive] for full imperative control over the animation loop. The callback reference is kept up-to-date via useLatest, so you always access the latest closure values without restarting the loop.
When to Use
- Building smooth animations that need to update on every browser paint frame (e.g., canvas drawing, CSS transforms)
- Implementing real-time visualizations like FPS counters, progress indicators, or physics simulations
- Running continuous visual updates that should pause and resume based on user interaction or visibility
Notes
- Auto-start: By default the loop starts immediately on mount. Pass
falseas the second argument to start in a paused state. - Cleanup: The animation frame is automatically cancelled on unmount via the effect cleanup.
- See also
useIntervalfor fixed-interval timing anduseUpdatefor triggering a single re-render on demand.
Usage
Live Editor
function Demo() { const [ticks, setTicks] = useState(0); const [lastCall, setLastCall] = useState(0); const update = useUpdate(); const [loopStop, loopStart, isActive] = useRafFn((time) => { setTicks(ticks => ticks + 1); setLastCall(time); }); return ( <div> <div>RAF triggered: {ticks} (times)</div> <div>Last high res timestamp: {lastCall}</div> <br /> <button onClick={() => { isActive() ? loopStop() : loopStart(); update(); }} > {isActive() ? "STOP" : "START"} </button> </div> ); };
Result
API
useRafFn
Returns
readonly [() => void, () => void, () => boolean]: A tuple with the following elements:
- stop function
- start function whether function is running
Arguments
| Argument | Description | Type | DefaultValue |
|---|---|---|---|
| callback | callback | FrameRequestCallback (Required) | - |
| initiallyActive | immediatly start | boolean | undefined | - |