UNPKG

@guanghechen/react-viewmodel

Version:
212 lines (199 loc) 7.36 kB
'use strict'; var viewmodel = require('@guanghechen/viewmodel'); var React = require('react'); var subscriber = require('@guanghechen/subscriber'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React); let didWarnOld18Alpha = false; let didWarnUncachedGetSnapshot = false; function useSyncExternalStore$2(subscribe, getSnapshot, _getServerSnapshot) { if (process.env.NODE_ENV === 'development') { if (!didWarnOld18Alpha) { if (React__namespace.startTransition !== undefined) { didWarnOld18Alpha = true; console.error('You are using an outdated, pre-release alpha of React 18 that ' + 'does not support useSyncExternalStore. The ' + 'use-sync-external-store shim will not work correctly. Upgrade ' + 'to a newer pre-release.'); } } } const value = getSnapshot(); if (process.env.NODE_ENV === 'development') { if (!didWarnUncachedGetSnapshot) { const cachedValue = getSnapshot(); if (!Object.is(value, cachedValue)) { console.error('The result of getSnapshot should be cached to avoid an infinite loop'); didWarnUncachedGetSnapshot = true; } } } const [{ inst }, forceUpdate] = React.useState({ inst: { value, getSnapshot } }); React.useLayoutEffect(() => { inst.value = value; inst.getSnapshot = getSnapshot; if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } }, [subscribe, value, getSnapshot]); React.useEffect(() => { if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } const handleStoreChange = () => { if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } }; return subscribe(handleStoreChange); }, [subscribe]); React.useDebugValue(value); return value; } function checkIfSnapshotChanged(inst) { const latestGetSnapshot = inst.getSnapshot; const prevValue = inst.value; try { const nextValue = latestGetSnapshot(); return !Object.is(prevValue, nextValue); } catch (_) { return true; } } function useSyncExternalStore$1(_subscribe, getSnapshot, _getServerSnapshot) { return getSnapshot(); } const canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined'); const shim = canUseDOM ? useSyncExternalStore$2 : useSyncExternalStore$1; const builtin = React__namespace.useSyncExternalStore; const useSyncExternalStore = builtin ? builtin : shim; function useComputed(computed$) { const { getSnapshot, getServerSnapshot, subscribeStateChange } = computed$; return useSyncExternalStore(subscribeStateChange, getSnapshot, getServerSnapshot); } function useObserveKey(collection, key) { const [state, setState] = React.useState(collection.get(key)); React.useEffect(() => { const subscriber$1 = new subscriber.Subscriber({ onNext: v => setState(v), }); const unsubscribable = collection.subscribeKey(key, subscriber$1); return () => { subscriber$1.dispose(); unsubscribable.unsubscribe(); }; }, [collection, key]); return state; } function useObserveSignal(viewmodel, keys) { const { ticker } = React.useMemo(() => viewmodel.ticker(keys), [viewmodel, ...keys]); const [signal, setSignal] = React.useState(0); React.useEffect(() => { const subscriber$1 = new subscriber.Subscriber({ onNext: () => setSignal(s => s + 1), }); const unsubscribable = ticker.subscribe(subscriber$1); return () => { subscriber$1.dispose(); unsubscribable.unsubscribe(); }; }, [ticker]); return signal; } function useStateValue(state$) { const { getSnapshot, getServerSnapshot, subscribeStateChange } = state$; return useSyncExternalStore(subscribeStateChange, getSnapshot, getServerSnapshot); } function useSetState(state$) { const { setState } = state$; return setState; } function useState(state$) { const { getSnapshot, getServerSnapshot, subscribeStateChange, setState } = state$; const state = useSyncExternalStore(subscribeStateChange, getSnapshot, getServerSnapshot); return [state, setState]; } function useReactState(state$) { const { getSnapshot, getServerSnapshot, subscribeStateChange, updateState } = state$; const state = useSyncExternalStore(subscribeStateChange, getSnapshot, getServerSnapshot); return [state, updateState]; } function useToggleState(state$) { const { setState } = state$; return React.useCallback(() => { setState(flag => !flag); }, [setState]); } const useViewModel = (fn) => { const ref = React.useRef(null); const [_, setTick] = React.useState(0); const fnRef = React.useRef(fn); fnRef.current = fn; React.useEffect(() => { let cancelled = false; if (!ref.current) { const promise = Promise.resolve(fnRef.current()); void promise .then((viewmodel) => { ref.current = viewmodel; const name = viewmodel.name || viewmodel.constructor.name; console.log(`[useViewModel] creating ${name}.`); if (!cancelled) { setTick(c => c + 1); } }) .catch(error => { ref.current = null; console.log('[useViewModel] failed. error:', error); if (!cancelled) { setTick(c => c + 1); } }); } return () => { cancelled = true; const viewmodel = ref.current; if (!viewmodel) return; const name = viewmodel.name || viewmodel.constructor.name; console.log(`[useViewModel] disposing ${name}.`); ref.current = null; viewmodel.dispose(); }; }, []); return ref.current; }; exports.useComputed = useComputed; exports.useObserveKey = useObserveKey; exports.useObserveSignal = useObserveSignal; exports.useReactState = useReactState; exports.useSetState = useSetState; exports.useState = useState; exports.useStateValue = useStateValue; exports.useSyncExternalStore = useSyncExternalStore; exports.useToggleState = useToggleState; exports.useViewModel = useViewModel; Object.keys(viewmodel).forEach(function (k) { if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, { enumerable: true, get: function () { return viewmodel[k]; } }); });