Matching Utilities

Redux Toolkit exports several type-safe action matching utilities that you can leverage when checking for specific kinds of actions. These are primarily useful for the builder.addMatcher() cases in createSlice and createReducer, as well as when writing custom middleware.

General Purpose

  • isAllOf - returns true when all conditions are met

  • isAnyOf - returns true when at least one of the conditions are met

createAsyncThunk-specific matchers

All these matchers can either be called with one or more thunks as arguments, in which case they will return a matcher function for that condition and thunks, or with one actions, in which case they will match for any thunk action with said condition.

  • isAsyncThunkAction - accepts one or more action creators and returns true when all match

  • isPending - accepts one or more action creators and returns true when all match

  • isFulfilled - accepts one or more action creators and returns true when all match

  • isRejected - accepts one or more action creators and returns true when all match

  • isRejectedWithValue - accepts one or more action creators and returns true when all match

isAllOf

A higher-order function that accepts one or more of:

  • redux-toolkit action creator functions such as the ones produced by:

  • type guard functions

  • custom action creator functions that have a .match property that is a type guard

It will return a type guard function that returns true if all of the provided functions match.

isAnyOf

Accepts the same inputs as isAllOf and will return a type guard function that returns true if at least one of the provided functions match.

isAsyncThunkAction

A higher-order function that returns a type guard function that may be used to check whether an action was created by createAsyncThunk.

```ts title="isAsyncThunkAction usage" import { isAsyncThunkAction, AnyAction } from '@reduxjs/toolkit' import { requestThunk1, requestThunk2 } from '@virtual/matchers'

const isARequestAction = isAsyncThunkAction(requestThunk1, requestThunk2)

function handleRequestAction(action: AnyAction) { if (isARequestAction(action)) { // action is an action dispatched by either requestThunk1 or requestThunk2 } }

isFulfilled

A higher-order function that returns a type guard function that may be used to check whether an action is a 'fulfilled'' action creator from the createAsyncThunk promise lifecycle.

```ts title="isFulfilled usage" import { isFulfilled, AnyAction } from '@reduxjs/toolkit' import { requestThunk1, requestThunk2 } from '@virtual/matchers'

const isAFulfilledAction = isFulfilled(requestThunk1, requestThunk2)

function handleFulfilledAction(action: AnyAction) { if (isAFulfilledAction(action)) { // action is a fulfilled action dispatched by either requestThunk1 or requestThunk2 } }

isRejectedWithValue

A higher-order function that returns a type guard function that may be used to check whether an action is a 'rejected' action creator from the createAsyncThunk promise lifecycle that was created by rejectWithValue.

```ts title="isRejectedWithValue usage" import { isRejectedWithValue, AnyAction } from '@reduxjs/toolkit' import { requestThunk1, requestThunk2 } from '@virtual/matchers'

const isARejectedWithValueAction = isRejectedWithValue( requestThunk1, requestThunk2 )

function handleRejectedWithValueAction(action: AnyAction) { if (isARejectedWithValueAction(action)) { // action is a rejected action dispatched by either requestThunk1 or requestThunk2 // where rejectWithValue was used } }

In this scenario, we can use isAllOf to simplify our code and reduce some of the boilerplate.

```ts title="Refactoring with isAllOf" import { createReducer, isAllOf } from '@reduxjs/toolkit' import { isSpecialAndInterestingThunk, initialState, isSpecial, isInteresting, Data } from '@virtual/matchers' // This is a fake pkg that provides the types shown above

const loadingReducer = createReducer(initialState, builder => { builder .addMatcher( isAllOf(isSpecialAndInterestingThunk.fulfilled, isSpecial), (state, action) => { state.isSpecial = true } ) .addMatcher( isAllOf(isSpecialAndInterestingThunk.fulfilled, isInteresting), (state, action) => { state.isInteresting = true } ) })

```ts title="Using isAnyOf as a type guard" import { isAnyOf, PayloadAction } from '@reduxjs/toolkit' import { Data, isSpecial, isInteresting } from '@virtual/matchers' // this is a fake pkg that provides the types shown above

const isSpecialOrInteresting = isAnyOf(isSpecial, isInteresting)

function someFunction(action: PayloadAction) { if (isSpecialOrInteresting(action)) { // "action" will be correctly typed as: // PayloadAction<Special> | PayloadAction<Interesting> } }

```

Example

<iframe src="https://codesandbox.io/embed/redux-toolkit-matchers-example-e765q?fontsize=14&hidenavigation=1&module=%2Fsrc%2Ffeatures%2Fcounter%2FcounterSlice.ts&theme=dark" style= title="redux-toolkit-matchers-example" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"

</iframe>

Last updated

Was this helpful?