UNPKG

reactive-react-redux

Version:

React Redux binding with React Hooks and Proxy

60 lines (55 loc) 1.81 kB
import { useContext, useEffect, useRef, useReducer, } from 'react'; import { defaultContext } from './Provider'; import { useIsomorphicLayoutEffect, useAffectedDebugValue } from './utils'; import { createDeepProxy, isDeepChanged } from './deepProxy'; export const useTrackedState = (opts = {}) => { const { customContext = defaultContext, } = opts; const [, forceUpdate] = useReducer((c) => c + 1, 0); const { state, subscribe } = useContext(customContext); const affected = new WeakMap(); const lastTracked = useRef(null); useIsomorphicLayoutEffect(() => { lastTracked.current = { state, affected, cache: new WeakMap(), /* eslint-disable no-nested-ternary, indent, @typescript-eslint/indent */ assumeChangedIfNotAffected: opts.unstable_forceUpdateForStateChange ? true : opts.unstable_ignoreIntermediateObjectUsage ? false : /* default */ null, /* eslint-enable no-nested-ternary, indent, @typescript-eslint/indent */ }; }); useEffect(() => { const callback = (nextState) => { if (lastTracked.current.state === nextState || !isDeepChanged( lastTracked.current.state, nextState, lastTracked.current.affected, lastTracked.current.cache, lastTracked.current.assumeChangedIfNotAffected, )) { // not changed return; } forceUpdate(); }; const unsubscribe = subscribe(callback); return unsubscribe; }, [subscribe]); if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks useAffectedDebugValue(state, affected); } const proxyCache = useRef(new WeakMap()); // per-hook proxyCache return createDeepProxy(state, affected, proxyCache.current); };