UNPKG

@guanghechen/react-hooks

Version:
117 lines (105 loc) 3.6 kB
'use strict'; 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;