You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Redux双Dispatch问题:同时触发请求状态被覆盖

问题原因与解决方案

核心问题:Reducer未保留原有状态

嘿,我一眼就发现问题出在你的Redux reducer里!你现在处理每个action时,直接返回了一个全新的对象,但完全没把之前状态里的其他字段合并进来。比如触发FETCH_DESIGN_CAT时,你只返回了designcat和loading,原来的foodcat、db这些字段直接被丢弃了;等第二个FETCH_FOOD_CAT触发时,又只返回了food(这里还有个字段名写错的小bug)和loading,自然就把第一个action更新的状态给覆盖了。

另外还有个细节错误:FETCH_FOOD_CAT里你把数据存在了food字段,但初始状态和mapStateToProps里用的都是foodcat,这会导致你根本拿不到食物分类的数据哦。

修复步骤

1. 修正Reducer的状态合并逻辑

修改你的reducer,每次返回新状态时,先用扩展运算符...state复制原有状态的所有字段,再覆盖需要更新的部分,同时修正字段名错误:

const initialState = {
  db: [],
  loading: true,
  designcat: [],
  foodcat: [],
}
export default (state = initialState, action) => {
  switch (action.type) {
    case FETCH_DESIGN_CAT:
      return {
        ...state, // 保留原有所有状态字段
        designcat: action.payload,
        loading: false,
      }
    case FETCH_FOOD_CAT:
      return {
        ...state, // 保留原有所有状态字段
        foodcat: action.payload, // 把food改成foodcat,和初始状态对应
        loading: false,
      }
    default: // 别忘了default分支,返回原有状态避免异常
      return state
  }
}

2. 修复服务器端路由的路径问题

你服务器端的两个GET路由都是"/",这肯定不对!虽然你说单个请求能工作,但应该是粘贴错误——毕竟你的action里请求的是"/api/designcategories"和"/api/foodcategories",所以服务器端的路由路径要对应修改:

// 设计分类路由
router.get("/designcategories", (req, res) => {
  let sql = "SELECT * FROM design_categories";
  let query = connection.query(sql, (err, results) => {
    if (err) throw err;
    res.header("Access-Control-Allow-Origin", "*");
    res.send(results);
  });
});
// 食物分类路由
router.get("/foodcategories", (req, res) => {
  let sql = "SELECT * FROM food_categories";
  let query = connection.query(sql, (err, results) => {
    if (err) throw err;
    res.header("Access-Control-Allow-Origin", "*");
    res.send(results);
  });
});

3. (可选)优化action中的异步逻辑

你的action里await和.then()混用了,简化一下让代码更清晰:

export const fetchDesignCat = () => {
  setLoading()
  return async dispatch => {
    try {
      const response = await axios.get("http://localhost:5000/api/designcategories");
      dispatch({ type: FETCH_DESIGN_CAT, payload: response.data });
    } catch (error) {
      console.log("await error", error);
    }
  }
}

export const fetchFoodCat = () => {
  setLoading()
  return async dispatch => {
    try {
      const response = await axios.get("http://localhost:5000/api/foodcategories");
      dispatch({ type: FETCH_FOOD_CAT, payload: response.data });
    } catch (error) {
      console.log("await error", error);
    }
  }
}

为什么这样能解决问题?

Redux的reducer是纯函数,每次更新状态都要返回新对象,但必须保留不需要修改的原有字段。用...state扩展运算符就能把之前状态里的所有属性复制到新对象里,再修改需要更新的字段,这样就不会覆盖之前action已经更新的内容了。

内容的提问来源于stack exchange,提问作者Marco Disco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 13:17:32