比對工具
Redux Toolkit 匯出多種類型安全的動作比對工具,當您檢查特定類型的動作時,您可以利用這些工具。這些工具主要用於 createSlice
和 createReducer
中的 builder.addMatcher()
案例,以及編寫自訂 Middleware 時。
一般用途
createAsyncThunk
專用比對器
所有這些比對器都可以使用一個或多個 thunk 作為引數來呼叫,這種情況下,它們會回傳該條件和 thunk 的比對器函式,或使用一個動作,這種情況下,它們會比對具有該條件的任何 thunk 動作。
isAsyncThunkAction
- 接受一個或多個動作建立器,並在所有比對都符合時回傳 trueisPending
- 接受一個或多個動作建立器,並在所有比對都符合時回傳 trueisFulfilled
- 接受一個或多個動作建立器,並在所有比對都符合時回傳 trueisRejected
- 接受一個或多個動作建立器,並在所有比對都符合時回傳 trueisRejectedWithValue
- 接受一個或多個動作建立器,並在所有比對都符合時回傳 true
isAllOf
接受一個或多個以下項目的高階函式
redux-toolkit
動作建立器函式,例如由下列函式產生的函式- 類型防護函式
- 具有
.match
屬性的自訂動作建立器函式,該屬性為類型防護
它將回傳一個類型防護函式,如果所有提供的函式都符合,則回傳 true
。
isAnyOf
接受與 isAllOf
相同的輸入,並將回傳一個類型防護函式,如果至少一個提供的函式符合,則回傳 true
。
isAsyncThunkAction
回傳類型防護函式的高階函式,可用於檢查動作是否由 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
回傳類型防護函式的高階函式,可用於檢查動作是否為來自 createAsyncThunk
承諾生命週期的「待處理」動作建立器。
- 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
回傳類型防護函式的高階函式,可用於檢查動作是否為來自 createAsyncThunk
承諾生命週期的「已完成」動作建立器。
- 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
承諾生命週期中的「已拒絕」動作建立器。
- 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
承諾生命週期中,由 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
模式建構簡化器時,我們一次新增一個案例或比對器。然而,透過使用 isAnyOf
或 isAllOf
,我們能夠輕鬆地以類型安全的方式,將同一個比對器用於多個案例。
首先,我們來檢視一個不必要的複雜範例
- 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>`
}
}