@naverpay/vanilla-store
Version:
  
63 lines (62 loc) • 2.11 kB
JavaScript
import { useRef, useEffect, useSyncExternalStore } from "react";
import { shallowEqual } from "./shallowEqual.mjs";
function useSyncStore(store, initialValue) {
const value = useSyncExternalStore(store.subscribe, store.get, () => initialValue || store.get());
return value;
}
const isNil = (value) => value == null;
function useSyncWithInitialValue(store, initialValue) {
const ref = useRef(initialValue || null);
useEffect(() => {
const serialized = store.persistStore?.serialized;
const persistValue = store.persistStore?.value;
if (!isNil(serialized) && !isNil(persistValue)) {
store.set(persistValue);
ref.current = null;
return;
}
if (!isNil(ref.current)) {
store.set(ref.current);
ref.current = null;
}
}, [store]);
}
function useStore(store, initialValue) {
useSyncWithInitialValue(store, initialValue);
const value = useSyncStore(store, initialValue);
return [value, store.set];
}
const useGetStore = (store, initialValue) => {
useSyncWithInitialValue(store, initialValue);
const value = useSyncStore(store, initialValue);
return value;
};
function useSetStore(store, initialValue) {
useSyncWithInitialValue(store, initialValue);
return store.set;
}
function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector, isEqual = shallowEqual) {
const initialSelection = selector(getSnapshot());
const stateRef = useRef(initialSelection);
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
const selection = selector(snapshot);
if (!isEqual(selection, stateRef.current)) {
stateRef.current = selection;
}
return stateRef.current;
}
function useStoreSelector(store, selector, options) {
const {
initialStoreValue,
isEqual
} = options || {};
useSyncWithInitialValue(store, initialStoreValue);
const value = useSyncExternalStoreWithSelector(store.subscribe, store.get, () => initialStoreValue || store.get(), selector, isEqual);
return [value, store.set];
}
export {
useGetStore,
useSetStore,
useStore,
useStoreSelector
};