Skip to content

Commit

Permalink
add isAction helper function, and ensure listener middleware only run…
Browse files Browse the repository at this point in the history
…s for actions
  • Loading branch information
ben.durrant committed Apr 17, 2023
1 parent eb586b6 commit 482270e
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 6 deletions.
18 changes: 14 additions & 4 deletions packages/toolkit/src/createAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export type PayloadActionCreator<
* A utility function to create an action creator for the given action type
* string. The action creator accepts a single argument, which will be included
* in the action object as a field called payload. The action creator function
* will also have its toString() overriden so that it returns the action type,
* will also have its toString() overridden so that it returns the action type,
* allowing it to be used in reducer logic that is looking for that action type.
*
* @param type The action type to use for created actions.
Expand All @@ -241,7 +241,7 @@ export function createAction<P = void, T extends string = string>(
* A utility function to create an action creator for the given action type
* string. The action creator accepts a single argument, which will be included
* in the action object as a field called payload. The action creator function
* will also have its toString() overriden so that it returns the action type,
* will also have its toString() overridden so that it returns the action type,
* allowing it to be used in reducer logic that is looking for that action type.
*
* @param type The action type to use for created actions.
Expand Down Expand Up @@ -286,15 +286,25 @@ export function createAction(type: string, prepareAction?: Function): any {
return actionCreator
}

/**
* Returns true if value is a plain object with a `type` property.
*/
export function isAction(action: unknown): action is Action<unknown> {
return isPlainObject(action) && 'type' in action
}

/**
* Returns true if value is an action with a string type and valid Flux Standard Action keys.
*/
export function isFSA(action: unknown): action is {
type: string
payload?: unknown
error?: unknown
meta?: unknown
} {
return (
isPlainObject(action) &&
typeof (action as any).type === 'string' &&
isAction(action) &&
typeof action.type === 'string' &&
Object.keys(action).every(isValidKey)
)
}
Expand Down
2 changes: 2 additions & 0 deletions packages/toolkit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export {
// js
createAction,
getType,
isAction,
isFSA as isFluxStandardAction,
} from './createAction'
export type {
// types
Expand Down
7 changes: 6 additions & 1 deletion packages/toolkit/src/listenerMiddleware/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Dispatch, AnyAction, MiddlewareAPI } from 'redux'
import type { ThunkDispatch } from 'redux-thunk'
import { createAction } from '../createAction'
import { createAction, isAction } from '../createAction'
import { nanoid } from '../nanoid'

import type {
Expand Down Expand Up @@ -426,6 +426,11 @@ export function createListenerMiddleware<

const middleware: ListenerMiddleware<S, D, ExtraArgument> =
(api) => (next) => (action) => {
if (!isAction(action)) {
// we only want to notify listeners for action objects
return next(action)
}

if (addListener.match(action)) {
return startListening(action.payload)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/toolkit/src/listenerMiddleware/tests/fork.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ describe('fork', () => {
},
})

store.dispatch(increment)
store.dispatch(increment())

expect(await deferredResult).toBe(listenerCompleted)
})
Expand Down

0 comments on commit 482270e

Please sign in to comment.