createAsyncThunk 是 Redux Toolkit 提供的一个核心工具,专门用于在 React Native(或 React)应用中处理异步操作。它能自动为您生成处理异步生命周期(pending, fulfilled, rejected)的 action,并将这些状态与您的 Redux store 紧密集成,从而极大地简化了异步逻辑的编写。
下面我将为您详细拆解它的用法,并提供一个完整的 React Native 示例。
一、核心概念
-
作用 :
createAsyncThunk接收一个 action type 前缀和一个返回 Promise 的函数作为参数。它会自动为您生成三种 action:-
type/pending:当异步操作开始时触发。 -
type/fulfilled:当异步操作成功完成时触发,并携带返回的数据。 -
type/rejected:当异步操作失败时触发,并携带错误信息。
-
-
优势 :相比传统的 Redux 异步中间件(如 redux-thunk),
createAsyncThunk能让您更清晰地分离异步逻辑和状态更新逻辑,并且能直接在createSlice的extraReducers中处理这些状态。
二、完整用法示例
我们以一个常见的场景为例:从 API 接口获取用户信息。
1. 定义异步操作(在 slice 文件中)
javascript
深色版本
// features/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios'; // 假设我们使用 axios 发起网络请求
// 第一步:定义异步操作
export const fetchUser = createAsyncThunk(
'user/fetchUser', // action type 前缀
async (userId, { rejectWithValue }) => {
try {
const response = await axios.get(`https://api.example.com/users/${userId}`);
return response.data; // 成功时返回的数据会传递给 fulfilled 的 reducer
} catch (error) {
// 捕获错误并返回,会传递给 rejected 的 reducer
return rejectWithValue(error.response?.data?.message || 'Failed to fetch user');
}
}
);
// 第二步:定义 slice
const userSlice = createSlice({
name: 'user',
initialState: {
data: null,
status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed'
error: null,
},
reducers: {
// 其他同步的 reducers
},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading';
state.error = null;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded';
state.data = action.payload; // 这里是接口返回的用户数据
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed';
state.error = action.payload; // 这里是错误信息
});
},
});
export default userSlice.reducer;
2. 在组件中调用异步操作
javascript
深色版本
// components/UserProfile.js
import React, { useEffect } from 'react';
import { View, Text, ActivityIndicator, Alert } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { fetchUser } from '../features/userSlice';
const UserProfile = ({ route }) => {
const { userId } = route.params;
const dispatch = useDispatch();
const { data: user, status, error } = useSelector((state) => state.user);
useEffect(() => {
// 第三步:在组件中调用 dispatch
dispatch(fetchUser(userId));
}, );
if (status === 'loading') {
return <ActivityIndicator size="large" />;
}
if (status === 'failed') {
return <Text style={{ color: 'red' }}>Error: {error}</Text>;
}
return (
<View>
<Text>Name: {user?.name}</Text>
<Text>Email: {user?.email}</Text>
</View>
);
};
export default UserProfile;
三、关键点总结
-
异步逻辑分离 :
createAsyncThunk将异步请求的逻辑(如网络请求)与状态更新逻辑(如设置 loading 状态)分离开,使代码更清晰。 -
状态自动管理 :通过
extraReducers处理pending、fulfilled、rejected三种状态,可以轻松地在 UI 中展示加载状态、成功数据或错误信息。 -
错误处理 :使用
rejectWithValue可以返回一个自定义的错误信息,而不是直接抛出异常,这样可以在rejected的 reducer 中更方便地处理。