React中如何从reducer函数中返回axios POST请求的执行结果
问题核心原因
- Redux/React useReducer 要求 reducer 是无副作用的纯函数,相同输入必须返回相同输出,禁止在 reducer 内部执行异步请求、修改外部变量这类副作用操作,你当前的写法本身就不符合 reducer 的设计规则。
- 异步请求的回调执行晚于 reducer 的 return 逻辑,因此你拿到的
updatedSingleQuestion永远是初始的undefined。
解决方案1:React 原生 useReducer 场景(无Redux中间件)
把异步请求逻辑从 reducer 中移到 dispatch 动作的位置,请求成功后再 dispatch 携带后端返回数据的动作:
调整后的dispatch调用逻辑(组件/自定义Hook内)
// 把异步逻辑写在dispatch之前 const handleIncreaseVote = async () => { // 先发POST请求 const res = await axios({ method: "POST", url: `http://localhost:5000/questions/${question_id}/votes-update`, withCredentials: true, data: { action: "increase", id: loginUser.id }, }) // 请求成功后再dispatch,把后端返回的结果放到payload里 dispatch({ type: "INCREASE_VOTES_QUESTION_SUCCESS", payload: res.data }) }
调整后的reducer逻辑
export default function reducer(state, action) { if (action.type === "INCREASE_VOTES_QUESTION_SUCCESS") { // 直接用action携带的后端返回数据更新state即可,reducer不再处理异步 return action.payload } // 其他action处理逻辑... }
如果还需要处理加载中、请求失败的状态,可以再加两个action类型:INCREASE_VOTES_QUESTION_LOADING、INCREASE_VOTES_QUESTION_ERROR,请求发起时dispatch loading动作更新加载状态,请求失败时dispatch error动作携带错误信息。
解决方案2:Redux 场景(使用redux-thunk中间件)
如果是用Redux做状态管理,可以引入redux-thunk中间件支持异步action:
第一步:定义异步action creator
// 异步action,返回接收dispatch的函数 export const increaseQuestionVote = (userId, questionId) => { return async (dispatch) => { dispatch({ type: "INCREASE_VOTES_QUESTION_LOADING" }) try { const res = await axios({ method: "POST", url: `http://localhost:5000/questions/${questionId}/votes-update`, withCredentials: true, data: { action: "increase", id: userId }, }) dispatch({ type: "INCREASE_VOTES_QUESTION_SUCCESS", payload: res.data }) } catch (err) { dispatch({ type: "INCREASE_VOTES_QUESTION_ERROR", payload: err.message }) } } }
第二步:组件内调用异步action
dispatch(increaseQuestionVote(loginUser.id, question_id))
第三步:reducer处理对应动作
export default function reducer(state, action) { switch(action.type) { case "INCREASE_VOTES_QUESTION_LOADING": return { ...state, loading: true, error: null } case "INCREASE_VOTES_QUESTION_SUCCESS": return { ...state, loading: false, data: action.payload } case "INCREASE_VOTES_QUESTION_ERROR": return { ...state, loading: false, error: action.payload } // 其他action逻辑 default: return state } }
内容的提问来源于stack exchange,提问作者Abhinav Pharswan
相关产品推荐
相关产品推荐

