向useState数组添加元素时出现重复添加的问题原因排查
React useState添加元素重复两次的原因分析
问题现象
使用React的useState钩子向数组中添加元素时,单个元素被重复添加两次。
相关代码
export default function App() { const [max, updateMax] = React.useState([]); const [mid, updateMid] = React.useState([]); const [low, updateLow] = React.useState([]); const arr = [ { letter: "A", number: 100 }, { letter: "B", number: 80 }, { letter: "C", number: 60 }, { letter: "D", number: 40 } ]; useEffect(() => { arr.map((element, index, array) => { element.number === 100 ? updateMax((prevState) => [...prevState, element.letter]) : element.number >= 60 ? updateMid((prevState) => [...prevState, element.letter]) : element.number < 60 ? updateLow((prevState) => [...prevState, element.letter]) : null; }); }, []); console.log(max, mid, low); return <div className="App"></div>; }
控制台输出
["A", "A"] ["B", "C", "B", "C"] ["D", "D"]
预期输出
["A"] ["B", "C"] ["D"]
原因解析
核心原因是**React严格模式(Strict Mode)**的影响:
- 在开发环境下,React严格模式会重复执行
useEffect回调、状态更新函数等逻辑,目的是帮开发者检测代码中潜在的副作用问题(比如未清理的定时器、重复订阅等)。 - 你的
useEffect依赖为空数组,本应仅执行一次,但在严格模式下会被执行两次;每次执行都会遍历arr,通过updateMax/updateMid/updateLow的函数式更新追加元素,最终导致每个元素被添加两次。
另外,代码里用map遍历却未使用返回值是个小问题,map是用于生成新数组的,仅做遍历操作时用forEach更合适,但这不是重复添加的直接原因。
解决思路
- 生产环境自动恢复正常:严格模式仅在开发环境生效,打包部署到生产环境后,该现象会自动消失。
- 优化状态更新逻辑:提前处理好所有分类数据,一次性更新状态,避免多次追加:
useEffect(() => { const newMax = []; const newMid = []; const newLow = []; arr.forEach(element => { if (element.number === 100) { newMax.push(element.letter); } else if (element.number >= 60) { newMid.push(element.letter); } else if (element.number < 60) { newLow.push(element.letter); } }); updateMax(newMax); updateMid(newMid); updateLow(newLow); }, []);
这种方式即使useEffect执行两次,第二次设置的是完整的分类数组,不会出现元素重复的情况。
3. 临时关闭严格模式(不推荐):如果需要在开发环境临时消除该现象,可以移除项目根组件外包裹的<React.StrictMode>标签,但会失去严格模式的副作用检测能力。
内容的提问来源于stack exchange,提问作者83hru2
相关产品推荐
相关产品推荐

