为何React中带空依赖数组的useEffect在初始渲染时执行两次?
开发环境下useEffect空依赖触发两次的原因及解决办法
原因
React 18在开发模式的StrictMode中,会刻意执行两次组件挂载、渲染相关的生命周期逻辑(包括useEffect),目的是帮你提前发现代码中潜在的问题,比如未清理的订阅、内存泄漏、重复执行导致的不一致状态等。你的代码里用了空依赖数组,在StrictMode下就会触发两次。
解决办法
1. 临时关闭StrictMode(不推荐长期使用)
如果只是想验证效果,可以在项目入口文件(通常是index.js或main.jsx)中移除<StrictMode>的包裹:
// 原代码 root.render( <StrictMode> <App /> </StrictMode> ); // 修改后 root.render( <App /> );
但不建议长期关闭,因为StrictMode能帮你提前排查很多隐藏问题。
2. 添加请求清理逻辑(推荐)
为了避免两次请求导致的资源浪费或状态异常,可以使用AbortController来中断未完成的请求,这也是React官方推荐的处理方式:
import { useEffect, useState } from "react"; function Users() { const [users, setUsers] = useState([]); useEffect(() => { const controller = new AbortController(); const signal = controller.signal; console.log("Fetching users..."); fetch("https://jsonplaceholder.typicode.com/users", { signal }) .then((res) => res.json()) .then((data) => setUsers(data)) .catch((err) => { // 忽略中止请求的错误 if (err.name !== "AbortError") { console.error("Fetch error:", err); } }); // 清理函数:组件卸载或重新执行useEffect时中断请求 return () => controller.abort(); }, []); return ( <div> <h2>User List</h2> <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> </div> ); }
这样即使useEffect执行两次,第一次的请求会被自动中止,不会重复更新状态。
内容的提问来源于stack exchange,提问作者sachin singh
相关产品推荐
相关产品推荐

