createAsyncThunk
是 Redux Toolkit 中的一个核心 API,专门用于简化 Redux 中异步操作(如 API 请求、定时任务等)的管理。它自动生成 pending/fulfilled/rejected 三种 action 类型,并处理异步流程的生命周期,减少开发者手动编写样板代码的工作量。
1. 核心作用
- 自动生成异步生命周期 Action:根据传入的
type
字符串,自动生成三种 action 类型(如type/pending
,type/fulfilled
,type/rejected
)。 - 封装异步逻辑:将异步操作(如 API 调用)封装成一个 thunk action,便于在 Redux 中统一管理。
- 简化错误处理:通过
try/catch
或 Promise 的reject
自动捕获错误,并触发rejected
action。
2. 函数签名
import { createAsyncThunk } from '@reduxjs/toolkit';
const asyncThunk = createAsyncThunk(
type: string, // 基础 action 类型(如 'users/fetch')
payloadCreator: (arg, thunkAPI) => Promise, // 异步逻辑
options?: { ... } // 可选配置
);
3. 参数详解
参数 1: type
- 作用:定义异步操作的基础类型字符串。
- 动态生成:可以通过函数动态生成 type(例如分页场景):
createAsyncThunk( (page) => `users/fetchPage/${page}`, async (page) => { /* ... */ } );
参数 2: payloadCreator
-
核心函数:包含异步逻辑(如 API 请求),必须返回一个 Promise。
-
参数:
arg
:调用 thunk 时传入的参数(如dispatch(fetchUser(123))
中的123
)。thunkAPI
:包含 Redux 相关方法和工具:dispatch
:Redux 的dispatch
方法。getState
:获取当前 Redux 状态。rejectWithValue
:将自定义错误传递给rejected
action。signal
:AbortController 的信号,用于取消请求。
-
示例:
const fetchUser = createAsyncThunk( 'user/fetch', async (userId, { rejectWithValue }) => { try { const response = await api.getUser(userId); return response.data; // 传递给 fulfilled action 的 payload } catch (err) { return rejectWithValue(err.response.data); // 传递给 rejected action 的 payload } } );
参数 3: options
(可选)
- 配置项,例如:
condition
: 控制是否执行异步逻辑(如避免重复请求)。dispatchConditionRejection
: 当condition
返回false
时,是否触发rejected
action。serializeError
: 自定义错误序列化逻辑。
4. 返回值
- thunk action creator:一个函数,当被
dispatch
时触发异步操作。 - 返回的 Promise:
- 如果异步成功,Promise 会 resolve 为
fulfilled
action 的 payload。 - 如果失败,Promise 会 reject 为
rejected
action 的 error。
- 如果异步成功,Promise 会 resolve 为
5. 处理 Action
在 Redux slice 的 extraReducers
中监听生成的三种 action:
const userSlice = createSlice({
name: 'user',
initialState: { data: null, loading: false, error: null },
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
})
.addCase(fetchUser.rejected, (state, action) => {
state.loading = false;
state.error = action.error.message; // 或 action.payload(如果用了 rejectWithValue)
});
},
});
6. 错误处理最佳实践
使用 rejectWithValue
传递错误信息:
const fetchUser = createAsyncThunk(
'user/fetch',
async (userId, { rejectWithValue }) => {
try {
const response = await api.getUser(userId);
return response.data;
} catch (err) {
// 返回自定义错误对象(而非默认的 Error 实例)
return rejectWithValue({
message: 'Failed to fetch user',
code: err.response.status,
});
}
}
);
在 reducer 中通过 action.payload
获取错误信息:
.addCase(fetchUser.rejected, (state, action) => {
state.error = action.payload; // { message: 'Failed...', code: 404 }
});
7. 使用场景
- 数据获取:从 API 获取数据并更新状态。
- 表单提交:处理用户提交的异步验证或保存操作。
- 复杂异步流程:如轮询、取消请求(结合
AbortController
)。
8. 注意事项
- 不要直接修改 state:在
payloadCreator
中只处理逻辑,状态更新在extraReducers
中进行。 - 错误需明确处理:未捕获的异常会导致 Promise 隐式 reject,但建议显式使用
rejectWithValue
。 - 取消请求:利用
signal
实现请求取消:const fetchUser = createAsyncThunk('user/fetch', async (_, { signal }) => { const response = await fetch('/api/user', { signal }); return response.json(); }); // 调用 abortController.abort() 取消请求
9. 总结
createAsyncThunk
是 Redux Toolkit 中处理异步操作的标准化方案,通过自动生成 action 类型和生命周期管理,显著减少冗余代码。结合 createSlice
的 extraReducers
,可以高效实现异步状态管理,尤其适合与 RTK Query 之外的 REST API 交互场景。