在State片段中使用异步函数
因为在Redux中,所有的Action都必须是同步的,所以不能直接在Reducer或者State片段中定义返回Promise
的异步Action。在传统Redux中,对于异步数据的支持也是通过redux-thunk或者redux-promise等中间件实现的。
其实要将异步过程加入到Redux的Action处理流程中,只需要将异步Action拆分成两个处理步骤即可,即启动异步Action的调用和处理Action的返回值。这样就可以将一个异步Action转换为两个同步的Action。
为了简化这个处理的过程,Redux Toolkit提供了一个名为createAsyncThunk
的函数来构建便于State片段处理的异步Action。
createAsyncThunk
函数可以接受三个参数来创建异步Action,以下是其函数签名。
// 用于向异步Action提供可供使用的额外功能与属性
// 从这个类型定义可以看出,异步处理函数中可以使用state、extra、dispatch函数等内容。
// 例如调用getState()可以获取state,调用dispatch()可以调用dispatch函数,
// 调用fulfillWithValue(value, meta)可以代替return从异步Action中返回处理成功的值,
// 调用rejectWithValue(value, meta)可以代替return或者thorw从异步Action中返回处理失败的值。
type GetThunkAPI<ThunkApiConfig> = BaseThunkAPI<
GetState<ThunkApiConfig>,
GetExtra<ThunkApiConfig>,
GetDispatch<ThunkApiConfig>,
GetRejectValue<ThunkApiConfig>,
GetRejectedMeta<ThunkApiConfig>,
GetFulfilledMeta<ThunkApiConfig>
>;
// 此类型定义了异步Action实际上是如何工作的,最终确认或者拒绝什么结果。这个类型在实际应用中实际上是一个返回了Promise类型值的异步函数。
// 这个异步函数只能接受一个参数,所以如果想要向函数传递多个参数,可以使用对象来组织。
type AsyncThunkPayloadCreator<Returned, ThunkArg = void, ThunkApiConfig extends AsyncThunkConfig = {}> = (
arg: ThunkArg,
thunkAPI: GetThunkAPI<ThunkApiConfig>
) => AsyncThunkPayloadCreatorReturnValue<Returned, ThunkApiConfig>;
// createAsyncThunk定义了一个异步Action本身,其第一个参数type用于定义这个action的基础action type。
// createAsyncThunk会使用给定的action type作为前缀创建三个用于第二步action处理的action type,分别是:
// pending,fulfilled,rejected,分别代表执行中、执行成功和执行失败。
function createAsyncThunk<Returned, ThunkArg = void>(
typePrefix: string,
payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, {}>,
options?: AsyncThunkOptions<ThunkArg, {}>
): AsyncThunk<Returned, ThunkArg, {}>;
这个函数签名看起来十分的复杂,但是createAsyncThunk
在使用的时候并不复杂。createAsyncThunk
定义的异步Action是以独立Action出现的,并不需要定义在State片段内部,但是在State片段内部还是需要对createAsyncThunk
创建的异步Action产生的结果Action进行处理。所需要处理的结果Action有以下几个。
.pending
,会根据createAsyncThunk
中提供的Action Type名称自动创建一个附加了/pending
的新Action Type,用于表示异步过程正在执行过程中。.fulfilled
,同样会自动创建一个附加了/fulfilled
的新Action Type,用于表示异步过程已经成功执行,并返回了成功执行的结果。.rejected
,会自动创建一个附加了/rejected
的新Action Type,用于表示异步过程出现错误,并返回了执行错误的信息。
对于异步Action的处理不能直接在State片段的reducers
属性中定义,只能在extraReducers
中定义。以下是延续上一节中的示例,并在其中增加了异步请求的Action。
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
interface CounterState {
value: number;
}
// 这个Action可以在应用中使用 dispatch(increaseByRemoteAmount(10)) 的形式来触发。
export const increaseByRemoteAmount = createAsyncThunk(
'counter/increateByRemoteAmount',
async (amount: number, thunkAPI) => {
const response = await fetch('/api/increase');
// 这里可以使用thunkAPI参数中提供的fulfillWithValue()方法,也可以直接使用return返回值。
thunkAPI.fulfillWithValue(response.amount);
}
);
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
// 这里延续上一节中定义的Reducer。
},
extraeReducers: builder => {
// builder中需要响应处理的是异步Action的fulfilled、rejected和pending这几个属性,
// 它们实际上就代表了异步Action在完成处理以后触发的Action的Action Type。
builder.addCase(increaseByRemoteAmount.fulfilled, (state, action) => {
// 从异步Action中返回的值,会保存在action的payload属性中传入。
state.value += action.payload;
});
}
});