@guanghechen/react-viewmodel
Version:
137 lines (128 loc) • 5.04 kB
JavaScript
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 };