跳到主要内容

 

匹配工具

Redux Toolkit 导出了几个类型安全的动作匹配工具,你可以在检查特定类型的动作时使用它们。这些主要用于 createSlicecreateReducer 中的 builder.addMatcher() 情况,以及编写自定义中间件时。

通用目的

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

createAsyncThunk-特定匹配器

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

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

isAllOf

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

  • redux-toolkit 动作创建函数,例如由以下产生的:
  • 类型保护函数
  • 自定义动作创建函数,具有 .match 属性,该属性是类型保护

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

isAnyOf

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

isAsyncThunkAction

一个高阶函数,返回一个类型保护函数,可以用来检查一个动作是否由 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)) {
// 动作是由 `requestThunk1` 或 `requestThunk2` 分派的动作
}
}

isPending

一个高阶函数,返回一个类型保护函数,可以用来检查一个动作是否是 createAsyncThunk promise 生命周期中的 'pending' 动作创建器。

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)) {
// 动作是由 `requestThunk1` 或 `requestThunk2` 分派的 pending 动作
}
}

isFulfilled

一个高阶函数,返回一个类型保护函数,可以用来检查一个动作是否是 createAsyncThunk promise 生命周期中的 'fulfilled' 动作创建器。

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)) {
// 动作是由 `requestThunk1` 或 `requestThunk2` 分派的 fulfilled 动作
}
}

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)) {
// 动作是由 `requestThunk1` 或 `requestThunk2` 分派的 rejected 动作
}
}

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)) {
// 动作是由 `requestThunk1` 或 `requestThunk2` 分派的 rejected 动作
// rejectWithValue 被使用
}
}

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

当使用 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,
}
},
)

// 这里有不必要的复杂性
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' // 这是一个提供上述类型的虚构包
import type { Data } from '@virtual/matchers' // 这是一个提供上述类型的虚构包

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' // 这是一个提供上述类型的虚构包
import type { Data } from '@virtual/matchers' // 这是一个提供上述类型的虚构包

const isSpecialAndInteresting = isAllOf(isSpecial, isInteresting)

function someFunction(action: PayloadAction<Data>) {
if (isSpecialAndInteresting(action)) {
// "action" 将被正确地类型化为:
// `PayloadAction<Special> & PayloadAction<Interesting>`
}
}
将 isAnyOf 用作类型保护
import { isAnyOf } from '@reduxjs/toolkit'
import type { PayloadAction } from '@reduxjs/toolkit'
import { Data, isSpecial, isInteresting } from '@virtual/matchers' // 这是一个提供上述类型的虚构包

const isSpecialOrInteresting = isAnyOf(isSpecial, isInteresting)

function someFunction(action: PayloadAction<Data>) {
if (isSpecialOrInteresting(action)) {
// "action" 将被正确地类型化为:
// `PayloadAction<Special> | PayloadAction<Interesting>`
}
}

示例