derive-zustand
Version:
A function to create a derived Zustand store from stores
80 lines (79 loc) • 2.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.derive = void 0;
function derive(deriveFn) {
const listeners = new Set();
const subscriptions = new Map();
let state;
let dependencies;
let invalidated = true;
const invalidate = () => {
if (invalidated) {
return;
}
invalidated = true;
listeners.forEach((listener) => listener(state, state));
};
const getState = () => {
if (!invalidated) {
return state;
}
if (!dependencies ||
Array.from(dependencies).some(([store, value]) => !Object.is(store.getState(), value))) {
const newDependencies = new Map();
const get = (store) => {
if (!store) {
return state;
}
const s = store.getState();
newDependencies.set(store, s);
return s;
};
state = deriveFn(get);
dependencies = newDependencies;
}
if (listeners.size) {
const deps = new Set(dependencies.keys());
subscriptions.forEach((unsubscribe, store) => {
if (deps.has(store)) {
deps.delete(store);
}
else {
unsubscribe();
subscriptions.delete(store);
}
});
deps.forEach((store) => {
subscriptions.set(store, store.subscribe(invalidate));
});
invalidated = false;
}
return state;
};
const subscribe = (listener) => {
listeners.add(listener);
return () => {
listeners.delete(listener);
if (!listeners.size) {
subscriptions.forEach((unsubscribe) => unsubscribe());
subscriptions.clear();
invalidated = true;
}
};
};
const store = {
getState,
subscribe,
getInitialState: () => {
throw new Error('getInitialState is not available in derived store');
},
setState: () => {
throw new Error('setState is not available in derived store');
},
destroy: () => {
throw new Error('destory is not available in derived store');
},
};
return store;
}
exports.derive = derive;