尝试展示列表添加的名称,但useEffect执行两次(Strict Mode已关)求协助
React useEffect 执行两次问题排查(已关闭 Strict Mode)
可能的触发原因
- 组件重复挂载:父组件状态变更、路由切换、key值不稳定等情况,会导致组件被卸载后重新挂载,进而触发空依赖的
useEffect执行两次。 - React 18+ 开发环境特性:即使关闭Strict Mode,Vite/CRA的热更新机制或React DevTools的部分设置,可能在开发阶段触发额外的渲染/挂载(生产环境会自动消失)。
- 状态初始化逻辑的连锁触发:原代码中第一个
useEffect通过setInputArr修改状态,会触发组件重渲染,若此时有其他逻辑(比如父组件的重渲染)叠加,可能被误认为是useEffect执行两次。
排查步骤
- 验证组件挂载状态:在组件中添加挂载/卸载日志,确认是否存在重复挂载:
useEffect(() => { console.log("组件已挂载"); return () => console.log("组件已卸载"); }, []);
如果日志中出现「卸载→重新挂载」,说明组件被重复创建,需要检查父组件的渲染逻辑(比如是否在循环中渲染组件、key值是否固定)。
- 检查开发环境配置:确认是否开启了React DevTools的「Highlight Updates」或其他调试功能,部分调试工具会强制触发重渲染;同时检查项目的热更新配置,是否存在代码修改外的自动刷新。
代码优化方案
原代码的两个useEffect存在逻辑冗余,且初始状态设置依赖useEffect容易触发不必要的重渲染,建议优化如下:
- 直接在
useState中初始化状态:避免用useEffect读取localStorage,减少一次初始渲染:
const [inputArr, setInputArr] = useState(() => { try { const itemsArr = window.localStorage.getItem("inputArr"); return itemsArr ? JSON.parse(itemsArr) : []; } catch (error) { console.error("解析localStorage中inputArr失败:", error); return []; } });
- 保留单个
useEffect负责持久化:仅在inputArr变更时写入localStorage,避免循环触发:
useEffect(() => { if (inputArr.length > 0) { window.localStorage.setItem("inputArr", JSON.stringify(inputArr)); } }, [inputArr]);
额外注意事项
- 若生产环境中也出现该问题,需排查是否存在全局状态(如Redux、Context)的频繁更新导致组件重复渲染。
- 确保
inputArr的修改操作没有触发意外的状态重置,比如在其他逻辑中误调用setInputArr覆盖原有值。
内容的提问来源于stack exchange,提问作者user27452169
相关产品推荐
相关产品推荐

