React Redux替换整个数组:如何避免dispatch调用触发无限循环
Redux useEffect触发无限循环的解决方法
问题场景
我是Redux新手,编写了如下Slice:
import { createSlice } from "@reduxjs/toolkit"; export const currentListSlice = createSlice({ name: "currentList", initialState: [1, 2, 3], // 开发用初始值,实际为空 reducers: { setCurrentList: (state, action) => { return action.payload; }, }, }); export const { setCurrentList } = currentListSlice.actions; export default currentListSlice.reducer;
通过useSelector获取状态生成渲染列表的逻辑运行正常:
const preList = useSelector((state) => state.currentList); const list = []; preList.map((item) => list.push(DATA[item]));
但在useEffect中调用dispatch更新状态时触发了无限循环:
useEffect(() => { dispatch(setCurrentList(fiveRandomBeaches(DATA.length))); }, [preList]);
测试通过按钮点击调用dispatch是正常的,随机数生成函数代码如下:
export const fiveRandomBeaches = (dataLength) => { let beachesList = []; let uniqueBeachesList; let rndBeach; do { rndMarker = Math.floor(Math.random() * dataLength); beachesList.push(rndMarker); uniqueBeachesList = [...new Set(beachesList)]; } while (uniqueBeachesList.length < 5); return uniqueBeachesList; };
原因分析
无限循环的核心原因是:
useEffect的依赖是preList,每次调用dispatch(setCurrentList(...))都会更新Redux中的currentList状态,导致preList拿到新的数组引用fiveRandomBeaches每次都会返回一个全新的数组对象(即使元素内容可能重复,引用也不同),这会让preList每次都被判定为“变化”,进而再次触发useEffect,形成循环
解决方案
根据实际需求选择对应的方案:
方案1:仅在组件挂载时执行一次
如果只需要在组件首次加载时生成随机列表,直接将useEffect的依赖改为空数组[],这样只会在组件挂载时执行一次:
useEffect(() => { dispatch(setCurrentList(fiveRandomBeaches(DATA.length))); }, []); // 空依赖,仅挂载时执行
方案2:仅在初始状态为空时执行
如果实际场景中初始currentList是空数组,需要在状态为空时才触发更新,可以添加条件判断:
useEffect(() => { // 仅当preList为空时才更新 if (preList.length === 0) { dispatch(setCurrentList(fiveRandomBeaches(DATA.length))); } }, [preList]);
内容的提问来源于stack exchange,提问作者user2100041
相关产品推荐
相关产品推荐

