zustand-computed
Version:
A Zustand middleware to create computed states.
53 lines (52 loc) • 1.88 kB
JavaScript
import { shallow } from "zustand/shallow";
//#region src/computed.ts
const computedImpl = (compute, opts) => (f) => {
const optsKeys = !opts || !("keys" in opts) || opts.keys == null ? void 0 : opts.keys;
const keysSet = optsKeys ? new Set(optsKeys) : void 0;
function defaultShouldRecomputeFn(_, nextState) {
if (!keysSet || nextState == null) return true;
return Object.keys(nextState).some((k) => keysSet.has(k));
}
const shouldRecomputeFn = opts && "shouldRecompute" in opts ? opts.shouldRecompute ?? defaultShouldRecomputeFn : defaultShouldRecomputeFn;
return (set, get, api) => {
const equalityFn = opts?.equalityFn ?? shallow;
function computeAndMerge(state, mutateInPlace = false) {
const computedState = compute(state);
for (const k of Object.keys(computedState)) if (k in state && equalityFn(computedState[k], state[k])) delete computedState[k];
return mutateInPlace ? Object.assign(state, computedState) : {
...state,
...computedState
};
}
const _api = api;
function setState(arg, replace) {
if (replace === false || replace == null) {
set((state) => {
const newState = typeof arg === "function" ? arg(state) : arg;
if (!shouldRecomputeFn(state, newState)) return newState;
if (typeof arg === "function" && newState === void 0) return computeAndMerge(state, true);
return computeAndMerge({
...state,
...newState
});
}, replace);
return;
}
set((state) => {
const newArg = arg;
const newState = typeof newArg === "function" ? newArg(state) : newArg;
if (!shouldRecomputeFn(state, newState)) return newState;
return computeAndMerge(newState);
}, replace);
}
_api.setState = setState;
const st = f(setState, get, _api);
return {
...st,
...compute(st)
};
};
};
const createComputed = computedImpl;
//#endregion
export { createComputed };