zustand
Version:
🐻 Bear necessities for state management in React
127 lines (122 loc) • 5.17 kB
JavaScript
System.register(['react'], (function (exports) {
'use strict';
var useReducer, useRef, useDebugValue, useEffect, useLayoutEffect;
return {
setters: [function (module) {
useReducer = module.useReducer;
useRef = module.useRef;
useDebugValue = module.useDebugValue;
useEffect = module.useEffect;
useLayoutEffect = module.useLayoutEffect;
}],
execute: (function () {
exports('default', create);
function createStore(createState) {
let state;
const listeners = /* @__PURE__ */ new Set();
const setState = (partial, replace) => {
const nextState = typeof partial === "function" ? partial(state) : partial;
if (nextState !== state) {
const previousState = state;
state = replace ? nextState : Object.assign({}, state, nextState);
listeners.forEach((listener) => listener(state, previousState));
}
};
const getState = () => state;
const subscribeWithSelector = (listener, selector = getState, equalityFn = Object.is) => {
console.warn("[DEPRECATED] Please use `subscribeWithSelector` middleware");
let currentSlice = selector(state);
function listenerToAdd() {
const nextSlice = selector(state);
if (!equalityFn(currentSlice, nextSlice)) {
const previousSlice = currentSlice;
listener(currentSlice = nextSlice, previousSlice);
}
}
listeners.add(listenerToAdd);
return () => listeners.delete(listenerToAdd);
};
const subscribe = (listener, selector, equalityFn) => {
if (selector || equalityFn) {
return subscribeWithSelector(listener, selector, equalityFn);
}
listeners.add(listener);
return () => listeners.delete(listener);
};
const destroy = () => listeners.clear();
const api = { setState, getState, subscribe, destroy };
state = createState(setState, getState, api);
return api;
}
const isSSR = typeof window === "undefined" || !window.navigator || /ServerSideRendering|^Deno\//.test(window.navigator.userAgent);
const useIsomorphicLayoutEffect = isSSR ? useEffect : useLayoutEffect;
function create(createState) {
const api = typeof createState === "function" ? createStore(createState) : createState;
const useStore = (selector = api.getState, equalityFn = Object.is) => {
const [, forceUpdate] = useReducer((c) => c + 1, 0);
const state = api.getState();
const stateRef = useRef(state);
const selectorRef = useRef(selector);
const equalityFnRef = useRef(equalityFn);
const erroredRef = useRef(false);
const currentSliceRef = useRef();
if (currentSliceRef.current === void 0) {
currentSliceRef.current = selector(state);
}
let newStateSlice;
let hasNewStateSlice = false;
if (stateRef.current !== state || selectorRef.current !== selector || equalityFnRef.current !== equalityFn || erroredRef.current) {
newStateSlice = selector(state);
hasNewStateSlice = !equalityFn(currentSliceRef.current, newStateSlice);
}
useIsomorphicLayoutEffect(() => {
if (hasNewStateSlice) {
currentSliceRef.current = newStateSlice;
}
stateRef.current = state;
selectorRef.current = selector;
equalityFnRef.current = equalityFn;
erroredRef.current = false;
});
const stateBeforeSubscriptionRef = useRef(state);
useIsomorphicLayoutEffect(() => {
const listener = () => {
try {
const nextState = api.getState();
const nextStateSlice = selectorRef.current(nextState);
if (!equalityFnRef.current(currentSliceRef.current, nextStateSlice)) {
stateRef.current = nextState;
currentSliceRef.current = nextStateSlice;
forceUpdate();
}
} catch (error) {
erroredRef.current = true;
forceUpdate();
}
};
const unsubscribe = api.subscribe(listener);
if (api.getState() !== stateBeforeSubscriptionRef.current) {
listener();
}
return unsubscribe;
}, []);
const sliceToReturn = hasNewStateSlice ? newStateSlice : currentSliceRef.current;
useDebugValue(sliceToReturn);
return sliceToReturn;
};
Object.assign(useStore, api);
useStore[Symbol.iterator] = function() {
console.warn("[useStore, api] = create() is deprecated and will be removed in v4");
const items = [useStore, api];
return {
next() {
const done = items.length <= 0;
return { value: items.shift(), done };
}
};
};
return useStore;
}
})
};
}));