React 教程

浏览7543
更新时间2025-08-20

useEffect Hook 允许您在组件中执行副作用。

副作用的一些示例是:获取数据、直接更新 DOM 和计时器。

useEffect 接受两个参数。 第二个参数是可选的。

useEffect(<function>, <dependency>)


我们以计时器为例。

实例:

使用 setTimeout() 计算初始渲染后 1 秒:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  });

  return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

运行实例 »

但是等等!! 它一直在计数,即使它应该只计数一次!

useEffect 在每个渲染上运行。 这意味着当计数发生变化时,会发生渲染,然后触发另一个效果。

这不是我们想要的。 有几种方法可以控制副作用何时运行。

我们应该始终包含接受数组的第二个参数。 我们可以选择将依赖项传递给此数组中的 useEffect

1. 没有传递依赖:

useEffect(() => {
  //在每个渲染上运行
});

2. 一个空数组:

useEffect(() => {
  //仅在第一次渲染时运行
}, []);

3. 道具或状态值:

useEffect(() => {
  //在第一次渲染时运行
  //并且任何时候任何依赖值发生变化
}, [prop, state]);

所以,为了解决这个问题,我们只在初始渲染上运行这个效果。

实例:

只在初始渲染上运行效果:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    setTimeout(() => {
      setCount((count) => count + 1);
    }, 1000);
  }, []); // <- 在此处添加空括号

  return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

运行实例 »

实例:

这是一个依赖于变量的 useEffect Hook 示例。 如果 count 变量更新,效果会再次运行:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function Counter() {
  const [count, setCount] = useState(0);
  const [calculation, setCalculation] = useState(0);

  useEffect(() => {
    setCalculation(() => count * 2);
  }, [count]); // <- 在此处添加计数变量

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount((c) => c + 1)}>+</button>
      <p>Calculation: {calculation}</p>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Counter />);

运行实例 »

如果有多个依赖项,则应将它们包含在 useEffect 依赖项数组中。


效果清理

有些效果需要清理以减少内存泄漏。

应该释放不再需要的超时、订阅、事件侦听器和其他效果。

我们通过在 useEffect Hook 的末尾包含一个返回函数来做到这一点。

实例:

useEffect Hook 结束时清理计时器:

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function Timer() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    let timer = setTimeout(() => {
    setCount((count) => count + 1);
  }, 1000);

  return () => clearTimeout(timer)
  }, []);

  return <h1>I've rendered {count} times!</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Timer />);

运行实例 »

注意:要清除计时器,我们必须为其命名。


学习训练

练习题:

您需要在 useEffect 钩子的第二个参数中添加什么以将其限制为仅在第一次渲染时运行?

import { useState, useEffect } from "react";
import ReactDOM from "react-dom/client";

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    setData(getData())
  }, );

  return <DisplayData data={data} />;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);

相关视频

更多

免费

前端入门_HTML5
初级前端入门_HTML5

64.8万次学习

收藏

免费

30分钟学会网站布局
初级30分钟学会网站布局

24.6万次学习

收藏

免费

CSS视频教程-玉女心经版
初级CSS视频教程-玉女心经版

41.1万次学习

收藏

免费

JavaScript极速入门_玉女心经系列
初级JavaScript极速入门_玉女心经系列

76.4万次学习

收藏

精品课程

更多
前端入门_HTML5
前端入门_HTML5

共29课时

64.9万人学习

CSS视频教程-玉女心经版
CSS视频教程-玉女心经版

共25课时

41.2万人学习

JavaScript极速入门_玉女心经系列
JavaScript极速入门_玉女心经系列

共43课时

76.6万人学习

独孤九贱(1)_HTML5视频教程
独孤九贱(1)_HTML5视频教程

共25课时

64.1万人学习

独孤九贱(2)_CSS视频教程
独孤九贱(2)_CSS视频教程

共22课时

24.3万人学习

独孤九贱(3)_JavaScript视频教程
独孤九贱(3)_JavaScript视频教程

共28课时

36.2万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时

133.1万人学习

热门下载

更多
phpStudy 2018最新版
phpStudy 2018最新版

集成PHP7,16种组合,超全大合集

下载

VC9 32位
VC9 32位

VC9 32位 phpstudy集成安装环境运行库

下载

VC11 32位
VC11 32位

VC11 32位 phpstudy集成安装环境运行库​

下载

php程序员工具箱完整版
php程序员工具箱完整版

程序员工具箱 v1.0 php集成环境

下载

VC14 32位
VC14 32位

VC14 32位 phpstudy安装环境运行库

下载

SublimeText3汉化版
SublimeText3汉化版

中文版,非常好用

下载

Notepad++ Windows版
Notepad++ Windows版

Notepad++ 8.9.7 Windows版官方安装包,适合 Windows 用户进行代码编辑、文本处理、语法高亮和插件扩展配置。

下载