ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
86 lines (74 loc) • 2.15 kB
text/typescript
import { useRef, useEffect, useState, useCallback } from 'react';
import isEqual from 'lodash/isEqual';
// thanks Kent C Dodds for the following helpers
/**
* @deprecated use `useState` instead, since React no longer
* issues warnings when calling setState on unmounted components.
*/
export function useSafeSetState<T>(
initialState?: T | (() => T)
): [T | undefined, React.Dispatch<React.SetStateAction<T>>] {
const [state, setState] = useState(initialState);
const mountedRef = useRef(false);
useEffect(() => {
mountedRef.current = true;
return () => {
mountedRef.current = false;
};
}, []);
const safeSetState = useCallback(
args => {
if (mountedRef.current) {
return setState(args);
}
},
[mountedRef, setState]
);
return [state, safeSetState];
}
export function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
export function useDeepCompareEffect(callback, inputs) {
const cleanupRef = useRef();
useEffect(() => {
if (!isEqual(previousInputs, inputs)) {
cleanupRef.current = callback();
}
return cleanupRef.current;
});
const previousInputs = usePrevious(inputs);
}
/**
* A hook that returns true once a delay has expired.
* @param ms The delay in milliseconds
* @param key A key that can be used to reset the timer
* @returns true if the delay has expired, false otherwise
*/
export function useTimeout(ms = 0, key = '') {
const [ready, setReady] = useState(false);
useEffect(() => {
setReady(false);
const timer = setTimeout(() => {
setReady(true);
}, ms);
return () => {
clearTimeout(timer);
};
}, [key, ms, setReady]);
return ready;
}
export function useIsMounted() {
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
};
}, []);
return isMounted;
}