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 metisAnyOf
- returns true when at least one of the conditions are met
createAsyncThunk
-specific matchers
createAsyncThunk
-specific matchersAll 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 matchisPending
- accepts one or more action creators and returns true when all matchisFulfilled
- accepts one or more action creators and returns true when all matchisRejected
- accepts one or more action creators and returns true when all matchisRejectedWithValue
- accepts one or more action creators and returns true when all match
isAllOf
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
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
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
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
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