From e20bddbd06e7c376f39c11a847b94043790e1079 Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Sun, 10 May 2020 19:02:17 +0200 Subject: [PATCH] change `preventPropagation` option to `api.stopPropagation` method --- etc/redux-toolkit.api.md | 9 +++++ src/createActionListenerMiddleware.test.ts | 26 +++---------- src/createActionListenerMiddleware.ts | 43 ++++++++++++++-------- src/index.ts | 4 +- 4 files changed, 45 insertions(+), 37 deletions(-) diff --git a/etc/redux-toolkit.api.md b/etc/redux-toolkit.api.md index 6abf7051b2..230417b021 100644 --- a/etc/redux-toolkit.api.md +++ b/etc/redux-toolkit.api.md @@ -51,6 +51,15 @@ export interface ActionCreatorWithPreparedPayload; } +// @alpha (undocumented) +export type ActionListener> = (action: A, api: ActionListenerMiddlewareAPI) => void; + +// @alpha (undocumented) +export interface ActionListenerMiddlewareAPI> extends MiddlewareAPI { + // (undocumented) + stopPropagation(): void; +} + // @public export interface ActionReducerMapBuilder { addCase>(actionCreator: ActionCreator, reducer: CaseReducer>): ActionReducerMapBuilder; diff --git a/src/createActionListenerMiddleware.test.ts b/src/createActionListenerMiddleware.test.ts index 22de0b4cfa..5665985334 100644 --- a/src/createActionListenerMiddleware.test.ts +++ b/src/createActionListenerMiddleware.test.ts @@ -9,7 +9,8 @@ import { AnyAction } from 'redux' const middlewareApi = { getState: expect.any(Function), - dispatch: expect.any(Function) + dispatch: expect.any(Function), + stopPropagation: expect.any(Function) } const noop = () => {} @@ -222,27 +223,12 @@ describe('createActionListenerMiddleware', () => { expect(reducer.mock.calls).toEqual([[{}, testAction1('a')]]) }) - test('"preventPropagation" prevents actions from being forwarded to the store', () => { + test('calling `api.stopPropagation` in the listeners prevents actions from being forwarded to the store', () => { reducer.mockClear() - const listener = jest.fn((_: TestAction1) => {}) - - middleware.addListener(testAction1, listener, { preventPropagation: true }) - - store.dispatch(testAction1('a')) - - expect(reducer.mock.calls).toEqual([]) - }) - - test('combining "preventPropagation" and "condition', () => { - reducer.mockClear() - - const listener = jest.fn((_: TestAction1) => {}) - - middleware.addListener(testAction1, listener, { - preventPropagation: true, - condition(action) { - return action.payload === 'b' + middleware.addListener(testAction1, (action: TestAction1, api) => { + if (action.payload === 'b') { + api.stopPropagation() } }) diff --git a/src/createActionListenerMiddleware.ts b/src/createActionListenerMiddleware.ts index 27b8b34cca..f2fd4ed383 100644 --- a/src/createActionListenerMiddleware.ts +++ b/src/createActionListenerMiddleware.ts @@ -2,11 +2,24 @@ import { Middleware, Dispatch, AnyAction, MiddlewareAPI, Action } from 'redux' import { TypedActionCreator } from './mapBuilders' import { createAction, BaseActionCreator } from './createAction' -type ActionListener> = ( - action: A, - api: MiddlewareAPI -) => void -interface ActionListenerOptions< +/** + * @alpha + */ +export interface ActionListenerMiddlewareAPI> + extends MiddlewareAPI { + stopPropagation(): void +} + +/** + * @alpha + */ +export type ActionListener< + A extends AnyAction, + S, + D extends Dispatch +> = (action: A, api: ActionListenerMiddlewareAPI) => void + +export interface ActionListenerOptions< A extends AnyAction, S, _ extends Dispatch @@ -15,21 +28,13 @@ interface ActionListenerOptions< * Indicates that the listener should be removed after if has run once. */ once?: boolean - /** - * If set to true, the action will not be forwarded to - * * listeners that were registered after this listener - * * middlewares later in the middleware chain - * * reducers - * If this listener is skipped due to `options.condition`, this has no effect. - */ - preventPropagation?: boolean /** * A function that determines if the listener should run, depending on the action and probably the state. */ condition?(action: A, getState: () => S): boolean } -interface AddListenerAction< +export interface AddListenerAction< A extends AnyAction, S, D extends Dispatch @@ -172,11 +177,17 @@ export function createActionListenerMiddleware< if (listeners) { for (const entry of listeners) { if (!entry.condition || entry.condition(action, api.getState)) { - entry.listener(action, api) + let preventPropagation = false + entry.listener(action, { + ...api, + stopPropagation() { + preventPropagation = true + } + }) if (entry.once) { listeners.delete(entry) } - if (entry.preventPropagation) { + if (preventPropagation) { return action } } diff --git a/src/index.ts b/src/index.ts index 3ebe6c6785..0cb8290ab9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -107,7 +107,9 @@ export { export { createActionListenerMiddleware, addListenerAction, - removeListenerAction + removeListenerAction, + ActionListener, + ActionListenerMiddlewareAPI } from './createActionListenerMiddleware' export { nanoid } from './nanoid'