UNPKG

derive-zustand

Version:

A function to create a derived Zustand store from stores

76 lines (75 loc) 2.33 kB
export 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; }