使用redux与redux-thunk时控制台打印store数据出现4次问题求解
问题原因
4次打印是开发环境下两个常见因素叠加导致的,不会影响线上生产环境运行:
- React 18 开发环境默认开启的严格模式(
<StrictMode>)会让组件初始化时执行两次渲染,用来检测代码中可能存在的副作用问题,生产环境会自动关闭该机制,这是前两次空数组打印的来源。 - 你的异步action触发了两次会改变
getCountriesDatastate的更新:请求成功后先触发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
相关产品推荐
相关产品推荐

