Redux中API调用应置于何处?是否应放在Actions中?
在Redux中放置API调用的正确位置
嘿,这个问题问得很关键!先直接纠正你的一个小误解:API调用绝对属于有副作用的操作——毕竟网络请求是异步的,会有延迟、失败、数据变化这些不可控的情况,而Redux里的纯action应该是只返回描述动作的普通对象,不能包含异步逻辑,所以直接把API调用放在action里是不合适的。
如果你想避开RxJS或Redux Saga,下面这两个官方支持的轻量方案完全能满足你的需求:
1. Redux Thunk(官方轻量中间件)
Thunk是Redux官方维护的中间件,它允许你的action creator返回一个函数而不是普通对象。这个函数可以接收dispatch和getState作为参数,你就能在里面处理异步API调用,然后根据请求的不同阶段(开始、成功、失败)dispatch对应的纯action。
举个简单的实现例子:
// 定义纯action类型常量 const FETCH_USERS_REQUEST = 'FETCH_USERS_REQUEST'; const FETCH_USERS_SUCCESS = 'FETCH_USERS_SUCCESS'; const FETCH_USERS_FAILURE = 'FETCH_USERS_FAILURE'; // 纯action创建函数 const fetchUsersRequest = () => ({ type: FETCH_USERS_REQUEST }); const fetchUsersSuccess = (users) => ({ type: FETCH_USERS_SUCCESS, payload: users }); const fetchUsersFailure = (error) => ({ type: FETCH_USERS_FAILURE, payload: error }); // 包含API调用的Thunk action creator export const fetchUsers = () => { return async (dispatch) => { dispatch(fetchUsersRequest()); // 通知Redux请求开始 try { const response = await fetch('https://api.example.com/users'); const data = await response.json(); dispatch(fetchUsersSuccess(data)); // 请求成功,分发数据 } catch (error) { dispatch(fetchUsersFailure(error.message)); // 请求失败,分发错误信息 } }; };
2. Redux Toolkit的createAsyncThunk(更简化的方式)
如果你已经在使用Redux Toolkit(现在官方强烈推荐的Redux开发方式),createAsyncThunk是处理异步API调用的绝佳选择——它帮你自动生成了请求pending/fulfilled/rejected三种状态的action,你只需要在slice里用extraReducers处理这些状态就行,代码更简洁易维护。
示例代码:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; // 创建异步Thunk,自动生成三种状态的action export const fetchUsers = createAsyncThunk( 'users/fetchUsers', async () => { const response = await fetch('https://api.example.com/users'); return response.json(); } ); // 定义用户状态切片 const usersSlice = createSlice({ name: 'users', initialState: { data: [], loading: false, error: null }, extraReducers: (builder) => { builder .addCase(fetchUsers.pending, (state) => { state.loading = true; state.error = null; }) .addCase(fetchUsers.fulfilled, (state, action) => { state.loading = false; state.data = action.payload; }) .addCase(fetchUsers.rejected, (state, action) => { state.loading = false; state.error = action.error.message; }); } }); export default usersSlice.reducer;
总结
- 不要把API调用放在纯action里,因为异步请求属于副作用,违反了Redux action的纯函数原则。
- 避开RxJS和Redux Saga的话,Redux Thunk和Redux Toolkit的createAsyncThunk是最适合的方案,它们都是轻量级、官方支持的工具,完全能覆盖大部分异步API调用的场景。
内容的提问来源于stack exchange,提问作者Robin D.
相关产品推荐
相关产品推荐

