madiator.com/ui/effects/use-throttle.js
2021-08-16 12:11:25 +02:00

50 lines
1.2 KiB
JavaScript

// @flow
import React from 'react';
const useEffectOnce = effect => {
React.useEffect(effect, []);
};
function useUnmount(fn: () => any): void {
const fnRef = React.useRef(fn);
// update the ref each render so if it change the newest callback will be invoked
fnRef.current = fn;
useEffectOnce(() => () => fnRef.current());
}
export function useThrottle(value: string, ms: number = 200) {
const [state, setState] = React.useState(value);
const timeout = React.useRef();
const nextValue = React.useRef(null);
const hasNextValue = React.useRef(0);
React.useEffect(() => {
if (!timeout.current) {
setState(value);
const timeoutCallback = () => {
if (hasNextValue.current) {
hasNextValue.current = false;
setState(nextValue.current);
timeout.current = setTimeout(timeoutCallback, ms);
} else {
timeout.current = undefined;
}
};
timeout.current = setTimeout(timeoutCallback, ms);
} else {
nextValue.current = value;
hasNextValue.current = true;
}
}, [value]);
useUnmount(() => {
timeout.current && clearTimeout(timeout.current);
});
return state;
}
export default useThrottle;