Skip to content

Commit

Permalink
change preventPropagation option to api.stopPropagation method
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed May 10, 2020
1 parent 91b1929 commit c04eb92
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 37 deletions.
9 changes: 9 additions & 0 deletions etc/redux-toolkit.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ export interface ActionCreatorWithPreparedPayload<Args extends unknown[], P, T e
(...args: Args): PayloadAction<P, T, M, E>;
}

// @public (undocumented)
export type ActionListener<A extends AnyAction, S, D extends Dispatch<AnyAction>> = (action: A, api: ActionListenerMiddlewareAPI<S, D>) => void;

// @public (undocumented)
export interface ActionListenerMiddlewareAPI<S, D extends Dispatch<AnyAction>> extends MiddlewareAPI<D, S> {
// (undocumented)
stopPropagation(): void;
}

// @public
export interface ActionReducerMapBuilder<State> {
addCase<ActionCreator extends TypedActionCreator<string>>(actionCreator: ActionCreator, reducer: CaseReducer<State, ReturnType<ActionCreator>>): ActionReducerMapBuilder<State>;
Expand Down
26 changes: 6 additions & 20 deletions src/createActionListenerMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {}
Expand Down Expand Up @@ -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()
}
})

Expand Down
37 changes: 21 additions & 16 deletions src/createActionListenerMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@ import { Middleware, Dispatch, AnyAction, MiddlewareAPI, Action } from 'redux'
import { TypedActionCreator } from './mapBuilders'
import { createAction, BaseActionCreator } from './createAction'

type ActionListener<A extends AnyAction, S, D extends Dispatch<AnyAction>> = (
action: A,
api: MiddlewareAPI<D, S>
) => void
interface ActionListenerOptions<
export interface ActionListenerMiddlewareAPI<S, D extends Dispatch<AnyAction>>
extends MiddlewareAPI<D, S> {
stopPropagation(): void
}

export type ActionListener<
A extends AnyAction,
S,
D extends Dispatch<AnyAction>
> = (action: A, api: ActionListenerMiddlewareAPI<S, D>) => void

export interface ActionListenerOptions<
A extends AnyAction,
S,
_ extends Dispatch<AnyAction>
Expand All @@ -15,21 +22,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<AnyAction>
Expand Down Expand Up @@ -172,11 +171,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
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export {
export {
createActionListenerMiddleware,
addListenerAction,
removeListenerAction
removeListenerAction,
ActionListener,
ActionListenerMiddlewareAPI
} from './createActionListenerMiddleware'

export { nanoid } from './nanoid'

0 comments on commit c04eb92

Please sign in to comment.