UNPKG

@guanghechen/react-viewmodel

Version:
137 lines (128 loc) 5.04 kB
import { Subscriber } from '@guanghechen/viewmodel'; export * from '@guanghechen/viewmodel'; import * as React from 'react'; import React__default, { useState as useState$1, useLayoutEffect, useEffect, useDebugValue } from 'react'; let didWarnOld18Alpha = false; let didWarnUncachedGetSnapshot = false; function useSyncExternalStore$2(subscribe, getSnapshot, _getServerSnapshot) { if (process.env.NODE_ENV === 'development') { if (!didWarnOld18Alpha) { if (React.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] = useState$1({ inst: { value, getSnapshot } }); useLayoutEffect(() => { inst.value = value; inst.getSnapshot = getSnapshot; if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } }, [subscribe, value, getSnapshot]); useEffect(() => { if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } const handleStoreChange = () => { if (checkIfSnapshotChanged(inst)) { forceUpdate({ inst }); } }; return subscribe(handleStoreChange); }, [subscribe]); 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.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__default.useState(collection.get(key)); React__default.useEffect(() => { const subscriber = new Subscriber({ onNext: v => setState(v), }); const unsubscribable = collection.subscribeKey(key, subscriber); return () => { subscriber.dispose(); unsubscribable.unsubscribe(); }; }, [collection, key]); return state; } function useObserveSignal(viewmodel, keys) { const { ticker } = React__default.useMemo(() => viewmodel.ticker(keys), [viewmodel, ...keys]); const [signal, setSignal] = React__default.useState(0); React__default.useEffect(() => { const subscriber = new Subscriber({ onNext: () => setSignal(s => s + 1), }); const unsubscribable = ticker.subscribe(subscriber); return () => { subscriber.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__default.useCallback(() => { setState(flag => !flag); }, [setState]); } export { useComputed, useObserveKey, useObserveSignal, useReactState, useSetState, useState, useStateValue, useSyncExternalStore, useToggleState };