@atlaskit/motion
Version:
A set of utilities to apply motion in your application.
65 lines (61 loc) • 1.83 kB
JavaScript
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);
}, []);
};