use-s-react
Version:
useS is a minimal yet powerful React hook for managing both local and global state — with zero boilerplate
50 lines (49 loc) • 1.76 kB
JavaScript
import { useMemo, useState, useCallback, useSyncExternalStore } from "react";
import { FullCopy } from "full-copy";
import { deepAssign, hasChanged, normalizeUseSArgs } from "../functions";
import { createState, setGlobalState, isKeyInitialized, getGlobalSnapshot, subscribeToGlobalState, } from "../store";
export function useS(config) {
const { initialValue, key } = normalizeUseSArgs(config);
if (key &&
typeof key === "string" &&
key.length > 0 &&
!isKeyInitialized(key)) {
createState(key, initialValue);
}
const [subscribe, getSnapshot] = useMemo(() => {
if (!key) {
return [() => () => { }, () => initialValue];
}
return [
(cb) => subscribeToGlobalState(key, cb),
() => getGlobalSnapshot(key),
];
}, [key, initialValue]);
const globalState = useSyncExternalStore(subscribe, getSnapshot);
const [localState, setLocalState] = useState(initialValue);
const setState = useCallback((val) => {
const current = key ? getGlobalSnapshot(key) : localState;
const resolved = typeof val === "function"
? val(current)
: val;
const { changed, type } = hasChanged(current, resolved);
if (!changed)
return;
let newState;
if (type === "object") {
const cloned = FullCopy(current);
deepAssign(cloned, resolved);
newState = cloned;
}
else {
newState = resolved;
}
if (key) {
setGlobalState(key, newState);
}
else {
setLocalState(newState);
}
}, [key, localState]);
return [key ? globalState : localState, setState];
}