@guanghechen/react-hooks
Version:
117 lines (105 loc) • 3.6 kB
JavaScript
;
var react = require('react');
var equal = require('@guanghechen/equal');
function useDeepCompareCallback(fn, deps) {
const signal = react.useRef(0);
const prevDeps = react.useRef(deps);
if (!equal.isEqual(prevDeps.current, deps))
signal.current += 1;
prevDeps.current = deps;
return react.useCallback(fn, [signal.current]);
}
function useEventCallback(handler) {
const handlerRef = react.useRef(handler);
react.useLayoutEffect(() => {
handlerRef.current = handler;
});
return react.useCallback((...args) => {
const handle = handlerRef.current;
return handle(...args);
}, []);
}
function useRefreshRef(value) {
const ref = react.useRef(value);
ref.current = value;
return ref;
}
function useBeforeUnloadEffect(fn, deps) {
const beforeunload = useDeepCompareCallback(fn, deps);
react.useLayoutEffect(() => {
window.addEventListener('beforeunload', beforeunload);
return () => window.removeEventListener('beforeunload', beforeunload);
}, [beforeunload]);
}
function useBeforeUnloadAsyncEffect(fn, preventDefault = true) {
const preventDefaultRef = useRefreshRef(preventDefault);
const beforeunload = useEventCallback(async (event) => {
if (preventDefaultRef.current === false) {
return fn(event);
}
event.preventDefault();
try {
await fn(event);
}
finally {
delete event.returnValue;
}
});
react.useLayoutEffect(() => {
window.addEventListener('beforeunload', beforeunload);
return () => window.removeEventListener('beforeunload', beforeunload);
}, [beforeunload]);
}
function useDeepCompareEffect(fn, deps) {
const signal = react.useRef(0);
const prevDeps = react.useRef(deps);
if (!equal.isEqual(prevDeps.current, deps))
signal.current += 1;
prevDeps.current = deps;
react.useEffect(fn, [signal.current]);
}
function useDeepCompareMemo(fn, deps) {
const signal = react.useRef(0);
const prevDeps = react.useRef(deps);
if (!equal.isEqual(prevDeps.current, deps))
signal.current += 1;
prevDeps.current = deps;
return react.useMemo(fn, [signal.current]);
}
function useInterval(callback, duration) {
const callbackRef = react.useRef(callback);
react.useEffect(() => {
callbackRef.current = callback;
}, [callback]);
react.useEffect(() => {
const tick = () => {
if (callbackRef.current === undefined)
return;
callbackRef.current();
};
const intervalId = setInterval(tick, duration);
return () => clearInterval(intervalId);
}, [duration]);
}
function usePreviousState(value) {
const ref = react.useRef(value);
react.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
function useSyncState(initialState) {
const [state, setState] = react.useState(initialState);
react.useEffect(() => setState(initialState), [initialState]);
return [state, setState];
}
exports.useBeforeUnloadAsyncEffect = useBeforeUnloadAsyncEffect;
exports.useBeforeUnloadEffect = useBeforeUnloadEffect;
exports.useDeepCompareCallback = useDeepCompareCallback;
exports.useDeepCompareEffect = useDeepCompareEffect;
exports.useDeepCompareMemo = useDeepCompareMemo;
exports.useEventCallback = useEventCallback;
exports.useInterval = useInterval;
exports.usePreviousState = usePreviousState;
exports.useRefreshRef = useRefreshRef;
exports.useSyncState = useSyncState;