为什么即使依赖数组为空,我的 React useEffect 钩子也会运行多次?

**问题**

在开发 React 项目时,我遇到了 useEffect 钩子的问题。我的目标是在组件挂载时仅从 API 获取一次数据。然而,即使我提供了一个空的依赖项数组,useEffect 仍会多次运行。

以下是代码片段:

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

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

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

Data

    {data.map(item => (
  • {item.name}
  • ))}
); }; export default MyComponent;

尽管依赖项数组 ([]) 为空,但 useEffect 仍被执行多次。我尝试重新启动开发服务器,但问题仍然存在。经过一番研究和故障排除,我找到了根本原因并解决了它。

**答案**

**为什么会发生这种情况**

如果您的应用在启用了 StrictMode 的情况下以 React 的开发模式运行,React 会故意多次挂载和卸载组件。这是一种仅限开发的行为,旨在检测可能导致问题的副作用。

在开发过程中,代码的变更可能会触发热模块替换,导致组件重新渲染,useEffect 再次执行。

**如何修复或处理此行为**

**识别严格模式:**

如果您使用的是 StrictMode,请了解此行为仅在开发中发生,不会影响生产版本。您可以通过删除

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(, document.getElementById("root"));

然而,最好保持其启用状态并调整您的代码以优雅地处理潜在的副作用。

**防止重复 API 调用:**

使用标志来确保 API 调用在组件的生命周期中只发生一次,即使

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) return;

    console.log("Fetching data...");
    axios.get("https://api.example.com/data")
      .then(response => setData(response.data))
      .catch(error => console.error(error));

    isFetched.current = true;
  }, []);

  return (
    

Data

    {data.map(item => (
  • {item.name}
  • ))}
); }; export default MyComponent;

使用 useRef 可确保 API 调用只发生一次,而不管 StrictMode 导致的额外渲染。

**关键要点**

。React 的严格模式在开发中是有意为之,可以安全地保留。

。生产版本不会出现此问题。。必要时使用 useRef 或其他技术来管理副作用。

必要时使用 useRef 或其他技术来管理副作用。

生产版本不会出现此问题。

必要时使用 useRef 或其他技术来管理副作用。