import { Selector } from 'reselect'; import type { ActionCreator, Store } from '../../store.js'; export interface Reaction { selector: Selector; reactor: ActionCreator; } export type Reactions = Reaction[]; export interface EqualityCheck { (a: any, b: any): boolean; } const defaultEqualityCheck: EqualityCheck = (a, b) => a === b; export const reactions = ( reactions: Reactions, isEqual: EqualityCheck = defaultEqualityCheck ) => { return (store: Store): Store => { const selectorValueCache = new WeakMap, unknown>(); store.addEventListener('state-change', async () => { for (const reaction of reactions) { const { selector, reactor } = reaction; const selectedValue = selector(store.state); const cachedValue = selectorValueCache.get(selector); if (isEqual(selectedValue, cachedValue)) { continue; } selectorValueCache.set(selector, selectedValue); await store.dispatch(reactor(selectedValue)); } }); return store; }; };