UNPKG

1.29 kBJavaScriptView Raw
1import { useRef } from 'react';
2import useMounted from './useMounted';
3import useStableMemo from './useStableMemo';
4import useWillUnmount from './useWillUnmount';
5/**
6 * Returns a controller object for requesting and cancelling an animation freame that is properly cleaned up
7 * once the component unmounts. New requests cancel and replace existing ones.
8 *
9 * ```ts
10 * const [style, setStyle] = useState({});
11 * const animationFrame = useAnimationFrame();
12 *
13 * const handleMouseMove = (e) => {
14 * animationFrame.request(() => {
15 * setStyle({ top: e.clientY, left: e.clientY })
16 * })
17 * }
18 *
19 * const handleMouseUp = () => {
20 * animationFrame.cancel()
21 * }
22 *
23 * return (
24 * <div onMouseUp={handleMouseUp} onMouseMove={handleMouseMove}>
25 * <Ball style={style} />
26 * </div>
27 * )
28 * ```
29 */
30export default function useAnimationFrame() {
31 const isMounted = useMounted();
32 const handle = useRef();
33 const cancel = () => {
34 if (handle.current != null) {
35 cancelAnimationFrame(handle.current);
36 }
37 };
38 useWillUnmount(cancel);
39 return useStableMemo(() => ({
40 request(cancelPrevious, fn) {
41 if (!isMounted()) return;
42 if (cancelPrevious) cancel();
43 handle.current = requestAnimationFrame(fn || cancelPrevious);
44 },
45 cancel
46 }), []);
47}
\No newline at end of file