UNPKG

@atlaskit/motion

Version:

A set of utilities to apply motion in your application.

65 lines (61 loc) 1.83 kB
import { useCallback, useEffect, useRef } from 'react'; // Handle both browser and Node.js environments const getHookDeps = opts => { switch (opts.cleanup) { case 'next-effect': return undefined; case 'unmount': default: return []; } }; /** * Will return request animation frame as a function which will clean itself up. */ export const useRequestAnimationFrame = (opts = { cleanup: 'unmount' }) => { const frames = useRef([]); useEffect(() => { return () => { if (frames.current.length) { frames.current.forEach(id => cancelAnimationFrame(id)); frames.current = []; } }; // We dynamically set this so we either clean up on the next effect - or on unmount. // eslint-disable-next-line react-hooks/exhaustive-deps }, getHookDeps(opts)); return useCallback(handler => { const id = requestAnimationFrame(time => { frames.current = frames.current.filter(frameId => frameId !== id); handler(time); }); frames.current.push(id); }, []); }; /** * Will return set timeout as a function which will clean itself up. */ export const useSetTimeout = (opts = { cleanup: 'unmount' }) => { const timeouts = useRef([]); useEffect(() => { return () => { if (timeouts.current.length) { timeouts.current.forEach(id => clearTimeout(id)); timeouts.current = []; } }; // We dynamically set this so we either clean up on the next effect - or on unmount. // eslint-disable-next-line react-hooks/exhaustive-deps }, getHookDeps(opts)); return useCallback((handler, timeout, ...args) => { const id = setTimeout(() => { timeouts.current = timeouts.current.filter(timeoutId => timeoutId !== id); handler(); }, timeout, ...args); timeouts.current.push(id); }, []); };