跳至主要内容

匹配实用程序

Redux Toolkit 导出了一些类型安全的动作匹配实用程序,您可以在检查特定类型的动作时利用它们。这些主要用于 createSlicecreateReducer 中的 builder.addMatcher() 案例,以及编写自定义中间件时。

通用

  • isAllOf - 当所有条件都满足时返回 true
  • isAnyOf - 当至少一个条件满足时返回 true

createAsyncThunk 特定匹配器

所有这些匹配器都可以接受一个或多个 thunk 作为参数,在这种情况下,它们将返回一个用于该条件和 thunk 的匹配器函数,或者接受一个 action,在这种情况下,它们将匹配具有该条件的任何 thunk action。

  • isAsyncThunkAction - 接受一个或多个 action 创建器,并在所有匹配时返回 true
  • isPending - 接受一个或多个 action 创建器,并在所有匹配时返回 true
  • isFulfilled - 接受一个或多个 action 创建器,并在所有匹配时返回 true
  • isRejected - 接受一个或多个 action 创建器,并在所有匹配时返回 true
  • isRejectedWithValue - 接受一个或多个 action 创建器,并在所有匹配时返回 true

isAllOf

一个高阶函数,它接受一个或多个

  • redux-toolkit action 创建器函数,例如由
  • 类型守卫函数
  • 具有 .match 属性(该属性是一个类型守卫)的自定义 action 创建器函数

它将返回一个类型守卫函数,如果所有提供的函数都匹配,则该函数返回 true

isAnyOf

接受与 isAllOf 相同的输入,并将返回一个类型守卫函数,如果至少一个提供的函数匹配,则该函数返回 true

isAsyncThunkAction

一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是由 createAsyncThunk 创建的。

isAsyncThunkAction 用法
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`
}
}

isPending

一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是 createAsyncThunk promise 生命周期中的 'pending' action 创建器。

isPending 用法
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`
}
}

isFulfilled

一个高阶函数,它返回一个类型守卫函数,该函数可用于检查一个 action 是否是 createAsyncThunk promise 生命周期中的 'fulfilled' action 创建器。

isFulfilled 用法
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`
}
}

isRejected

一个高阶函数,返回一个类型保护函数,可用于检查操作是否来自createAsyncThunk Promise 生命周期中的“rejected”操作创建者。

isRejected 用法
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`
}
}

isRejectedWithValue

一个高阶函数,返回一个类型保护函数,可用于检查操作是否来自createAsyncThunk Promise 生命周期中的“rejected”操作创建者,该操作创建者是由rejectWithValue创建的。

isRejectedWithValue 用法
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
}
}

使用匹配器来减少代码复杂度、重复和样板代码

在使用builder模式构建 reducer 时,我们一次添加一个 case 或匹配器。但是,通过使用isAnyOfisAllOf,我们能够以类型安全的方式轻松地将相同的匹配器用于多个 case。

首先,让我们检查一个不必要的复杂示例

不使用匹配器实用程序的示例
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
}
})
})

在这种情况下,我们可以使用isAllOf来简化我们的代码并减少一些样板代码。

使用 isAllOf 重构
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
}
)
})

使用匹配器作为 TypeScript 类型保护

isAllOfisAnyOf返回的函数也可以用作其他上下文中的 TypeScript 类型保护。

使用 isAllOf 作为类型保护
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>`
}
}
使用 isAnyOf 作为类型保护
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>`
}
}

示例