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

React useEffect空依赖数组仍多次执行的问题排查与解决

问题解答

1. 空依赖数组下useEffect仍多次执行的原因

在React 17的开发环境中,Strict Mode(严格模式)会主动重复执行挂载阶段的effect。这是React的内置校验机制,目的是帮你检测未正确清理的副作用(比如未取消的订阅、遗留定时器等),提前发现潜在问题。你的空依赖数组写法本身是正确的,但严格模式的这个开发专属逻辑导致了effect多次执行。

2. 是否与React开发环境的严格模式有关?

是的,完全相关。React严格模式仅在开发环境生效,它会:

  • 两次调用组件的render函数、构造函数
  • 两次执行挂载阶段的useEffect(空依赖数组的effect)
  • 两次调用useState、useReducer的初始化函数
    该行为是开发环境的校验逻辑,生产环境下不会触发,你的代码在生产环境中只会执行一次API请求。

3. 如何确保useEffect按预期仅执行一次?

有三种可行方案:

方案一:直接部署到生产环境

生产环境下React会自动关闭严格模式的重复执行逻辑,你的现有代码无需修改,就能保证effect只执行一次。

方案二:开发环境临时关闭严格模式

若开发阶段不想看到重复执行的情况,可修改项目入口文件(通常是index.js),移除包裹组件的<React.StrictMode>标签:

// 修改前
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// 修改后
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

注意:不建议长期关闭严格模式,它能帮你提前排查很多潜在问题。

方案三:用ref标记执行状态

如果想保留严格模式,同时让API请求只执行一次,可通过useRef记录执行状态:

import React, { useEffect, useState, useRef } from "react";
import axios from "axios";

const MyComponent = () => {
    const [data, setData] = useState([]);
    const isFetched = useRef(false);

    useEffect(() => {
        if (!isFetched.current) {
            console.log("Fetching data...");
            axios.get("https://jsonplaceholder.typicode.com/posts")
                .then(response => setData(response.data))
                .catch(error => console.error(error));
            isFetched.current = true;
        }
    }, []);

    return (
        <div>
            <h1>Data</h1>
            <ul>
                {data.map(item => (
                    <li key={item.id}>{item.title}</li>
                ))}
            </ul>
        </div>
    );
};

export default MyComponent;

借助isFetched这个ref的状态,即使严格模式触发两次effect,实际的API请求也只会执行一次。


内容的提问来源于stack exchange,提问作者Ravindra Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:47:42