如何用Redux Thunk与async/await调度多Action,跟踪Axios加载状态?
如何用Async/Await配合Redux跟踪Axios请求的加载状态
我来帮你梳理下怎么实现这个需求,其实思路很清晰——我们可以把「触发加载状态」和「执行Axios请求」的逻辑放在同一个异步action creator里,完全保持async/await的整洁风格。下面一步步来:
第一步:编写处理加载状态的Reducer
首先我们的Reducer需要维护三个核心状态:user(存储请求到的用户数据)、isFetching(标记是否正在请求)、error(存储请求错误信息)。示例代码如下:
const initialState = { user: null, isFetching: false, error: null }; const userReducer = (state = initialState, action) => { switch (action.type) { case 'FETCHING_USER': return { ...state, isFetching: true, error: null // 请求开始前重置错误状态 }; case 'FETCH_USER_SUCCESS': return { ...state, isFetching: false, user: action.payload }; case 'FETCH_USER_FAILURE': return { ...state, isFetching: false, error: action.payload }; default: return state; } };
第二步:编写支持Async/Await的Action Creators
这里需要用到redux-thunk中间件(Redux默认不支持返回函数的异步action,thunk可以帮我们实现这一点)。我们先定义三个基础的同步action creator,然后在异步action creator里按顺序调度它们:
import axios from 'axios'; // 同步action:标记请求开始 const fetchingUser = () => ({ type: 'FETCHING_USER' }); // 同步action:请求成功,存储用户数据 const fetchUserSuccess = (user) => ({ type: 'FETCH_USER_SUCCESS', payload: user }); // 同步action:请求失败,存储错误信息 const fetchUserFailure = (error) => ({ type: 'FETCH_USER_FAILURE', payload: error }); // 异步action creator:用async/await组织逻辑 export const fetchUser = (userId) => async (dispatch) => { try { // 第一步:先调度FETCHING_USER,把isFetching设为true dispatch(fetchingUser()); // 第二步:执行Axios GET请求,用await等待结果 const response = await axios.get(`/api/users/${userId}`); // 请求成功,调度成功action dispatch(fetchUserSuccess(response.data)); } catch (error) { // 请求失败,调度失败action,同时把isFetching设回false dispatch(fetchUserFailure(error.message)); } };
第三步:确保Redux Store启用Thunk中间件
如果你的Store还没配置thunk,需要在创建Store的时候加上:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; // 你的根Reducer const store = createStore(rootReducer, applyMiddleware(thunk));
第四步:在UI组件中使用
比如在React组件里,我们可以用useDispatch和useSelector来触发请求并获取状态:
import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { fetchUser } from './actions/userActions'; function UserProfile({ userId }) { const dispatch = useDispatch(); const { user, isFetching, error } = useSelector(state => state.user); useEffect(() => { // 组件挂载时触发用户请求 dispatch(fetchUser(userId)); }, [dispatch, userId]); // 根据状态渲染不同UI if (isFetching) return <div>正在加载用户信息...</div>; if (error) return <div>加载失败:{error}</div>; if (!user) return <div>未找到用户</div>; return ( <div className="user-profile"> <h2>{user.name}</h2> <p>邮箱:{user.email}</p> </div> ); }
这种写法完全符合你想要的async/await风格,逻辑顺序清晰:先标记加载中,再执行请求,最后根据请求结果更新状态,同时始终保证isFetching能被正确重置,不会一直停留在加载状态。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

