You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:52:18