diff --git a/src/Updux.ts b/src/Updux.ts index baa5a6e..062eb31 100644 --- a/src/Updux.ts +++ b/src/Updux.ts @@ -45,10 +45,10 @@ type ResolveAction< ? ActionArg : ActionArg extends (...args: any) => any ? ActionCreatorWithPreparedPayload< - Parameters, - ReturnType, - ActionType - > + Parameters, + ReturnType, + ActionType + > : ActionCreatorWithoutPayload; type ResolveActions< @@ -56,10 +56,10 @@ type ResolveActions< [key: string]: any; }, > = { - [ActionType in keyof A]: ActionType extends string + [ActionType in keyof A]: ActionType extends string ? ResolveAction : never; -}; + }; type Reaction = ( api: M, @@ -311,8 +311,30 @@ export default class Updux< this.#defaultMutation = { mutation, terminal }; } - addEffect(effect: EffectMiddleware) { + addEffect(actionCreator: + AggregateActions, T_Subduxes>, + effect: EffectMiddleware): EffectMiddleware; + addEffect(effect: EffectMiddleware): EffectMiddleware; + addEffect(...args) { + let effect; + if (args.length === 1) { + effect = args[0]; + } + else { + const [actionCreator, originalEffect] = args; + + effect = (api) => next => { + const e = originalEffect(api)(next); + return action => { + const func = actionCreator.match(action) ? e : next; + return func(action); + } + } + } + this.#localEffects.push(effect); + + return effect; } get effectsMiddleware() { diff --git a/src/effects.test.ts b/src/effects.test.ts index 007abb4..0d93fa9 100644 --- a/src/effects.test.ts +++ b/src/effects.test.ts @@ -39,7 +39,7 @@ test('buildEffectsMiddleware', () => { expect(seen).toEqual(0); const dispatch = vi.fn(); - mw({ getState: () => 'the state', dispatch })(() => {})({ + mw({ getState: () => 'the state', dispatch })(() => { })({ type: 'noop', }); expect(seen).toEqual(1); @@ -106,5 +106,30 @@ test('subdux', () => { expect(seen).toEqual(1); }); +test('addEffect with actionCreator', () => { + const dux = new Updux({ + actions: { + foo: null, + bar: null, + }, + }); + + const next = vi.fn(); + const spy = vi.fn(); + + const mw = dux.addEffect(dux.actions.foo, (api) => (next) => (action) => + next(spy(action)) + ); + + mw({})(next)(dux.actions.bar()); + expect(next).toHaveBeenCalled(); + expect(spy).not.toHaveBeenCalled(); + + next.mockReset(); + mw({})(next)(dux.actions.foo()); + expect(next).toHaveBeenCalled(); + expect(spy).toHaveBeenCalled(); +}); + // TODO subdux effects // TODO allow to subscribe / unsubscribe effects?