effect with actionCreator

This commit is contained in:
Yanick Champoux 2023-04-21 15:11:32 -04:00
parent 9fe6fc952e
commit 55f0d5cd13
2 changed files with 55 additions and 8 deletions

View File

@ -45,10 +45,10 @@ type ResolveAction<
? ActionArg ? ActionArg
: ActionArg extends (...args: any) => any : ActionArg extends (...args: any) => any
? ActionCreatorWithPreparedPayload< ? ActionCreatorWithPreparedPayload<
Parameters<ActionArg>, Parameters<ActionArg>,
ReturnType<ActionArg>, ReturnType<ActionArg>,
ActionType ActionType
> >
: ActionCreatorWithoutPayload<ActionType>; : ActionCreatorWithoutPayload<ActionType>;
type ResolveActions< type ResolveActions<
@ -56,10 +56,10 @@ type ResolveActions<
[key: string]: any; [key: string]: any;
}, },
> = { > = {
[ActionType in keyof A]: ActionType extends string [ActionType in keyof A]: ActionType extends string
? ResolveAction<ActionType, A[ActionType]> ? ResolveAction<ActionType, A[ActionType]>
: never; : never;
}; };
type Reaction<S = any, M extends MiddlewareAPI = MiddlewareAPI> = ( type Reaction<S = any, M extends MiddlewareAPI = MiddlewareAPI> = (
api: M, api: M,
@ -311,8 +311,30 @@ export default class Updux<
this.#defaultMutation = { mutation, terminal }; this.#defaultMutation = { mutation, terminal };
} }
addEffect(effect: EffectMiddleware) { addEffect(actionCreator:
AggregateActions<ResolveActions<T_LocalActions>, 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); this.#localEffects.push(effect);
return effect;
} }
get effectsMiddleware() { get effectsMiddleware() {

View File

@ -39,7 +39,7 @@ test('buildEffectsMiddleware', () => {
expect(seen).toEqual(0); expect(seen).toEqual(0);
const dispatch = vi.fn(); const dispatch = vi.fn();
mw({ getState: () => 'the state', dispatch })(() => {})({ mw({ getState: () => 'the state', dispatch })(() => { })({
type: 'noop', type: 'noop',
}); });
expect(seen).toEqual(1); expect(seen).toEqual(1);
@ -106,5 +106,30 @@ test('subdux', () => {
expect(seen).toEqual(1); 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 subdux effects
// TODO allow to subscribe / unsubscribe effects? // TODO allow to subscribe / unsubscribe effects?