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

使用redux与redux-thunk时控制台打印store数据出现4次问题求解

问题原因

4次打印是开发环境下两个常见因素叠加导致的,不会影响线上生产环境运行:

  • React 18 开发环境默认开启的严格模式(<StrictMode>)会让组件初始化时执行两次渲染,用来检测代码中可能存在的副作用问题,生产环境会自动关闭该机制,这是前两次空数组打印的来源。
  • 你的异步action触发了两次会改变getCountriesData state的更新:请求成功后先触发GET_ALL_COUNTRIES更新allCountries字段,再触发SET_LOADING更新loading字段。每次state更新都会触发组件重渲染,对应后两次新数据的打印。你当前useSelector的写法是直接取整个state.getCountriesData对象,只要该对象引用变化就会触发重渲染,不管实际用到的字段有没有变化。

解决方法

方法1:优化useSelector取值(推荐)

将批量取值改为分别取对应字段,减少不必要的重渲染触发:

// 原来的写法
const { allCountries, loading } = useSelector(
  (state) => state.getCountriesData
);

// 修改为
const allCountries = useSelector(state => state.getCountriesData.allCountries);
const loading = useSelector(state => state.getCountriesData.loading);

方法2:合并dispatch,减少state更新次数

请求成功后更新数据的同时顺便修改loading状态,去掉多余的dispatch:
首先修改action代码:

export const getAllCountries = () => {
  return async (dispatch) => {
    dispatch(setLoading(true));
    const res = await axios.get(`https://restcountries.eu/rest/v2/all`);
    dispatch({
      type: "GET_ALL_COUNTRIES",
      payload: res.data,
    });
    // 删除单独的setLoading(false)调用
  };
};

再修改reducer中GET_ALL_COUNTRIES的逻辑:

case "GET_ALL_COUNTRIES":
  return {
    ...state,
    allCountries: action.payload,
    loading: false // 新增,更新数据同时关闭加载状态
  };

方法3:临时关闭严格模式(不推荐)

如果只是觉得重复打印影响调试,可以找到项目入口文件(一般是index.js),删除外层的<React.StrictMode>标签即可,不过严格模式可以帮你提前发现很多问题,不建议长期关闭。

方法4:将打印逻辑放到useEffect中

如果你只需要监控allCountries的变化,可以把console.log放到依赖为allCountries的useEffect中,避免loading变化导致的多余打印:

useEffect(() => {
  console.log(allCountries);
}, [allCountries]);

内容的提问来源于stack exchange,提问作者Anshu Verma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 13:09:01