diff --git a/src/Updux.ts b/src/Updux.ts index 6063217..8045e73 100644 --- a/src/Updux.ts +++ b/src/Updux.ts @@ -6,6 +6,7 @@ import { Action, MiddlewareAPI, AnyAction, + Middleware, } from 'redux'; import { configureStore, @@ -88,7 +89,7 @@ export default class Updux< >; #selectors: any; - #effects: any[] = []; + #localEffects: Middleware[] = []; constructor( config: Partial<{ @@ -128,19 +129,42 @@ export default class Updux< return this.#initial; } + get effects() { + return [ + ...this.#localEffects, + ...Object.entries(this.#subduxes).flatMap( + ([slice, { effects }]) => { + if (!effects) return []; + return effects.map(effect => (api) => effect({ + ...api, + getState: () => api.getState()[slice], + })) + } + ) + ] + } + createStore( options: Partial<{ initial: T_LocalState; }> = {}, ) { const preloadedState: any = options.initial ?? this.initial; + + const effects = buildEffectsMiddleware( + this.effects, + this.actions, + this.selectors, + ); + + const store = configureStore({ reducer: ((state) => state) as Reducer< AggregateState, AnyAction >, preloadedState, - middleware: [this.effectsMiddleware], + middleware: [effects], }); const dispatch: any = store.dispatch; @@ -221,11 +245,7 @@ export default class Updux< } addEffect(effect: EffectMiddleware) { - this.#effects.push(effect); - } - - get effects() { - return this.#effects; + this.#localEffects.push(effect); } get effectsMiddleware() { diff --git a/src/effects.test.ts b/src/effects.test.ts index 906d83b..f500cae 100644 --- a/src/effects.test.ts +++ b/src/effects.test.ts @@ -75,5 +75,36 @@ test('basic', () => { expect(seen).toEqual(1); }); +test('subdux', () => { + const bar = new Updux({ + initial: 'bar state', + actions: { foo: 0 }, + }); + + let seen = 0; + bar.addEffect((api) => next => action => { + seen++; + expect(api.getState()).toBe('bar state'); + next(action); + }); + + const dux = new Updux({ + initial: { + loaded: true, + }, + subduxes: { + bar + }, + }); + + const store = dux.createStore(); + + expect(seen).toEqual(0); + + store.dispatch.foo(); + + expect(seen).toEqual(1); +}); + // TODO subdux effects // TODO allow to subscribe / unsubscribe effects? diff --git a/src/types.ts b/src/types.ts index cca0034..2420635 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { Action, ActionCreator, Reducer } from 'redux'; +import { Action, ActionCreator, Middleware, Reducer } from 'redux'; export type Dux< STATE = any, @@ -11,6 +11,7 @@ export type Dux< state: STATE, action: ReturnType, ) => STATE; + effects: Middleware[]; }>; type ActionsOf = DUX extends { actions: infer A } ? A : {};