匹配实用程序
Redux Toolkit 导出了一些类型安全的动作匹配实用程序,您可以在检查特定类型的动作时利用它们。这些主要用于 createSlice
和 createReducer
中的 builder.addMatcher()
案例,以及编写自定义中间件时。
通用
createAsyncThunk
特定匹配器
所有这些匹配器都可以接受一个或多个 thunk 作为参数,在这种情况下,它们将返回一个用于该条件和 thunk 的匹配器函数,或者接受一个 action,在这种情况下,它们将匹配具有该条件的任何 thunk action。
isAsyncThunkAction
- 接受一个或多个 action 创建器,并在所有匹配时返回 trueisPending
- 接受一个或多个 action 创建器,并在所有匹配时返回 trueisFulfilled
- 接受一个或多个 action 创建器,并在所有匹配时返回 trueisRejected
- 接受一个或多个 action 创建器,并在所有匹配时返回 trueisRejectedWithValue
- 接受一个或多个 action 创建器,并在所有匹配时返回 true
isAllOf
一个高阶函数,它接受一个或多个
redux-toolkit
action 创建器函数,例如由- 类型守卫函数
- 具有
.match
属性(该属性是一个类型守卫)的自定义 action 创建器函数
它将返回一个类型守卫函数,如果所有提供的函数都匹配,则该函数返回 true
。
isAnyOf
接受与 isAllOf
相同的输入,并将返回一个类型守卫函数,如果至少一个提供的函数匹配,则该函数返回 true
。
isAsyncThunkAction
一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是由 createAsyncThunk
创建的。
- TypeScript
- JavaScript
import { isAsyncThunkAction } from '@reduxjs/toolkit'
import type { UnknownAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARequestAction = isAsyncThunkAction(requestThunk1, requestThunk2)
function handleRequestAction(action: UnknownAction) {
if (isARequestAction(action)) {
// action is an action dispatched by either `requestThunk1` or `requestThunk2`
}
}
import { isAsyncThunkAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARequestAction = isAsyncThunkAction(requestThunk1, requestThunk2)
function handleRequestAction(action) {
if (isARequestAction(action)) {
// action is an action dispatched by either `requestThunk1` or `requestThunk2`
}
}
isPending
一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是 createAsyncThunk
promise 生命周期中的 'pending' action 创建器。
- TypeScript
- JavaScript
import { isPending } from '@reduxjs/toolkit'
import type { UnknownAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isAPendingAction = isPending(requestThunk1, requestThunk2)
function handlePendingAction(action: UnknownAction) {
if (isAPendingAction(action)) {
// action is a pending action dispatched by either `requestThunk1` or `requestThunk2`
}
}
import { isPending } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isAPendingAction = isPending(requestThunk1, requestThunk2)
function handlePendingAction(action) {
if (isAPendingAction(action)) {
// action is a pending action dispatched by either `requestThunk1` or `requestThunk2`
}
}
isFulfilled
一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是 createAsyncThunk
promise 生命周期中的 'fulfilled' action 创建器。
- TypeScript
- JavaScript
import { isFulfilled } from '@reduxjs/toolkit'
import type { UnknownAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isAFulfilledAction = isFulfilled(requestThunk1, requestThunk2)
function handleFulfilledAction(action: UnknownAction) {
if (isAFulfilledAction(action)) {
// action is a fulfilled action dispatched by either `requestThunk1` or `requestThunk2`
}
}
import { isFulfilled } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isAFulfilledAction = isFulfilled(requestThunk1, requestThunk2)
function handleFulfilledAction(action) {
if (isAFulfilledAction(action)) {
// action is a fulfilled action dispatched by either `requestThunk1` or `requestThunk2`
}
}
isRejected
一个高阶函数,返回一个类型保护函数,可用于检查操作是否来自createAsyncThunk
Promise 生命周期中的“rejected”操作创建者。
- TypeScript
- JavaScript
import { isRejected } from '@reduxjs/toolkit'
import type { UnknownAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARejectedAction = isRejected(requestThunk1, requestThunk2)
function handleRejectedAction(action: UnknownAction) {
if (isARejectedAction(action)) {
// action is a rejected action dispatched by either `requestThunk1` or `requestThunk2`
}
}
import { isRejected } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARejectedAction = isRejected(requestThunk1, requestThunk2)
function handleRejectedAction(action) {
if (isARejectedAction(action)) {
// action is a rejected action dispatched by either `requestThunk1` or `requestThunk2`
}
}
isRejectedWithValue
一个高阶函数,返回一个类型保护函数,可用于检查操作是否来自createAsyncThunk
Promise 生命周期中的“rejected”操作创建者,该操作创建者是由rejectWithValue
创建的。
- TypeScript
- JavaScript
import { isRejectedWithValue } from '@reduxjs/toolkit'
import type { UnknownAction } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARejectedWithValueAction = isRejectedWithValue(
requestThunk1,
requestThunk2
)
function handleRejectedWithValueAction(action: UnknownAction) {
if (isARejectedWithValueAction(action)) {
// action is a rejected action dispatched by either `requestThunk1` or `requestThunk2`
// where rejectWithValue was used
}
}
import { isRejectedWithValue } from '@reduxjs/toolkit'
import { requestThunk1, requestThunk2 } from '@virtual/matchers'
const isARejectedWithValueAction = isRejectedWithValue(
requestThunk1,
requestThunk2
)
function handleRejectedWithValueAction(action) {
if (isARejectedWithValueAction(action)) {
// action is a rejected action dispatched by either `requestThunk1` or `requestThunk2`
// where rejectWithValue was used
}
}
使用匹配器来减少代码复杂度、重复和样板代码
在使用builder
模式构建 reducer 时,我们一次添加一个 case 或匹配器。但是,通过使用isAnyOf
或isAllOf
,我们能够以类型安全的方式轻松地将相同的匹配器用于多个 case。
首先,让我们检查一个不必要的复杂示例
- TypeScript
- JavaScript
import { createAsyncThunk, createReducer } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
interface Data {
isInteresting: boolean
isSpecial: boolean
}
interface Special extends Data {
isSpecial: true
}
interface Interesting extends Data {
isInteresting: true
}
function isSpecial(
action: PayloadAction<Data>
): action is PayloadAction<Special> {
return action.payload.isSpecial
}
function isInteresting(
action: PayloadAction<Data>
): action is PayloadAction<Interesting> {
return action.payload.isInteresting
}
interface ExampleState {
isSpecial: boolean
isInteresting: boolean
}
const initialState = {
isSpecial: false,
isInteresting: false,
} satisfies ExampleState as ExampleState
export const isSpecialAndInterestingThunk = createAsyncThunk(
'isSpecialAndInterestingThunk',
() => {
return {
isSpecial: true,
isInteresting: true,
}
}
)
// This has unnecessary complexity
const loadingReducer = createReducer(initialState, (builder) => {
builder.addCase(isSpecialAndInterestingThunk.fulfilled, (state, action) => {
if (isSpecial(action)) {
state.isSpecial = true
}
if (isInteresting(action)) {
state.isInteresting = true
}
})
})
import { createAsyncThunk, createReducer } from '@reduxjs/toolkit'
function isSpecial(action) {
return action.payload.isSpecial
}
function isInteresting(action) {
return action.payload.isInteresting
}
const initialState = {
isSpecial: false,
isInteresting: false,
}
export const isSpecialAndInterestingThunk = createAsyncThunk(
'isSpecialAndInterestingThunk',
() => {
return {
isSpecial: true,
isInteresting: true,
}
}
)
// This has unnecessary complexity
const loadingReducer = createReducer(initialState, (builder) => {
builder.addCase(isSpecialAndInterestingThunk.fulfilled, (state, action) => {
if (isSpecial(action)) {
state.isSpecial = true
}
if (isInteresting(action)) {
state.isInteresting = true
}
})
})
在这种情况下,我们可以使用isAllOf
来简化我们的代码并减少一些样板代码。
- TypeScript
- JavaScript
import { createReducer, isAllOf } from '@reduxjs/toolkit'
import {
isSpecialAndInterestingThunk,
initialState,
isSpecial,
isInteresting,
} from '@virtual/matchers' // This is a fake pkg that provides the types shown above
import type { 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
}
)
})
import { createReducer, isAllOf } from '@reduxjs/toolkit'
import {
isSpecialAndInterestingThunk,
initialState,
isSpecial,
isInteresting,
} 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
}
)
})
使用匹配器作为 TypeScript 类型保护
isAllOf
和isAnyOf
返回的函数也可以用作其他上下文中的 TypeScript 类型保护。
- TypeScript
- JavaScript
import { isAllOf } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { isSpecial, isInteresting } from '@virtual/matchers' // This is a fake pkg that provides the types shown above
import type { Data } from '@virtual/matchers' // This is a fake pkg that provides the types shown above
const isSpecialAndInteresting = isAllOf(isSpecial, isInteresting)
function someFunction(action: PayloadAction<Data>) {
if (isSpecialAndInteresting(action)) {
// "action" will be correctly typed as:
// `PayloadAction<Special> & PayloadAction<Interesting>`
}
}
import { isAllOf } from '@reduxjs/toolkit'
import { isSpecial, isInteresting } from '@virtual/matchers' // This is a fake pkg that provides the types shown above
const isSpecialAndInteresting = isAllOf(isSpecial, isInteresting)
function someFunction(action) {
if (isSpecialAndInteresting(action)) {
// "action" will be correctly typed as:
// `PayloadAction<Special> & PayloadAction<Interesting>`
}
}
- TypeScript
- JavaScript
import { isAnyOf } from '@reduxjs/toolkit'
import type { 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<Data>) {
if (isSpecialOrInteresting(action)) {
// "action" will be correctly typed as:
// `PayloadAction<Special> | PayloadAction<Interesting>`
}
}
import { isAnyOf } from '@reduxjs/toolkit'
import { isSpecial, isInteresting } from '@virtual/matchers' // this is a fake pkg that provides the types shown above
const isSpecialOrInteresting = isAnyOf(isSpecial, isInteresting)
function someFunction(action) {
if (isSpecialOrInteresting(action)) {
// "action" will be correctly typed as:
// `PayloadAction<Special> | PayloadAction<Interesting>`
}
}