【React】useEffect 钩子详解

news2024/9/9 1:01:26

文章目录

    • 一、useEffect 概念
    • 二、useEffect 的基本用法
      • 1. 无依赖项
      • 2. 空依赖项数组
      • 3. 带依赖项的 useEffect
    • 三、useEffect 的常见应用场景
      • 1. 数据获取
      • 2. 订阅与清除
      • 3. 动画与定时器
    • 四、useEffect 的进阶用法
      • 1. 多个 useEffect
      • 2. 条件执行副作用
    • 五、注意事项

useEffect 是 React 钩子函数之一,它使函数组件能够执行副作用操作。常见的副作用包括数据获取、订阅、手动更改 React 组件中的 DOM 以及定时器等。在类组件中,我们通常在生命周期方法中执行这些操作,而在函数组件中,我们使用 useEffect 来完成这些任务。本文将详细介绍 useEffect 的概念、用法及其在实际开发中的应用,旨在帮助开发者全面掌握这一重要特性。

一、useEffect 概念

useEffect 钩子是 React 16.8 版本引入的,它允许我们在函数组件中执行副作用操作。useEffect 函数接收两个参数:

  1. 一个副作用函数。
  2. 一个依赖项数组(可选)。

基本语法如下:

useEffect(() => {
  // 副作用逻辑
  return () => {
    // 清除逻辑(可选)
  };
}, [依赖项]);

二、useEffect 的基本用法

1. 无依赖项

如果不传递依赖项数组,副作用函数会在每次渲染后执行。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('组件渲染或更新了');

    return () => {
      console.log('组件卸载了');
    };
  });

  return <div>Hello, useEffect!</div>;
}

上述代码中,console.log 会在每次组件渲染或更新时执行,而返回的清除函数会在组件卸载时执行。

2. 空依赖项数组

如果传递一个空数组作为依赖项,副作用函数只会在组件首次渲染时执行一次。

import React, { useEffect } from 'react';

function MyComponent() {
  useEffect(() => {
    console.log('组件首次渲染');

    return () => {
      console.log('组件卸载');
    };
  }, []);

  return <div>Hello, useEffect!</div>;
}

3. 带依赖项的 useEffect

如果传递一个依赖项数组,副作用函数会在依赖项发生变化时执行。

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    console.log(`Count 发生变化: ${count}`);

    return () => {
      console.log(`清除副作用: ${count}`);
    };
  }, [count]);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
    </div>
  );
}

上述代码中,当 count 发生变化时,副作用函数会执行,同时会先执行上一次渲染中的清除函数。

三、useEffect 的常见应用场景

1. 数据获取

在函数组件中使用 useEffect 可以方便地进行数据获取。

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));

    // 清除逻辑
    return () => {
      // 取消请求或其他清除操作
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  if (!data) {
    return <div>Loading...</div>;
  }

  return <div>{JSON.stringify(data)}</div>;
}

2. 订阅与清除

useEffect 也可以用于设置和清除订阅,例如事件监听器或 WebSocket 连接。

import React, { useEffect } from 'react';

function EventListenerComponent() {
  useEffect(() => {
    const handleResize = () => {
      console.log('窗口大小改变');
    };

    window.addEventListener('resize', handleResize);

    // 清除逻辑
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  return <div>请调整窗口大小查看效果</div>;
}

3. 动画与定时器

我们可以使用 useEffect 来设置和清除定时器或启动动画。

import React, { useState, useEffect } from 'react';

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

  useEffect(() => {
    const intervalId = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);

    // 清除逻辑
    return () => {
      clearInterval(intervalId);
    };
  }, []); // 空依赖数组表示只在组件挂载和卸载时执行

  return <div>计数: {count}</div>;
}

四、useEffect 的进阶用法

1. 多个 useEffect

在一个组件中可以使用多个 useEffect,每个 useEffect 可以负责不同的副作用操作。

import React, { useState, useEffect } from 'react';

function MultiEffectComponent() {
  const [count, setCount] = useState(0);
  const [data, setData] = useState(null);

  useEffect(() => {
    document.title = `计数: ${count}`;
  }, [count]);

  useEffect(() => {
    fetch('https://api.example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <div>数据: {JSON.stringify(data)}</div>
    </div>
  );
}

2. 条件执行副作用

通过条件判断,可以有选择地执行副作用逻辑。

import React, { useState, useEffect } from 'react';

function ConditionalEffectComponent() {
  const [count, setCount] = useState(0);
  const [fetchData, setFetchData] = useState(false);
  const [data, setData] = useState(null);

  useEffect(() => {
    if (fetchData) {
      fetch('https://api.example.com/data')
        .then(response => response.json())
        .then(data => setData(data));
    }
  }, [fetchData]);

  return (
    <div>
      <p>计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>增加</button>
      <button onClick={() => setFetchData(true)}>获取数据</button>
      <div>数据: {JSON.stringify(data)}</div>
    </div>
  );
}

五、注意事项

  1. 避免不必要的副作用:确保副作用函数只在需要时执行。使用依赖项数组来控制副作用的执行时机,避免不必要的重复执行。
  2. 清除副作用:副作用函数返回的清除函数用于清理不再需要的副作用。例如,清除事件监听器、取消订阅或清除定时器等。
  3. 依赖项数组:准确指定依赖项数组中的变量,确保副作用函数在依赖项发生变化时正确执行。遗漏或误包含依赖项可能导致副作用执行不符合预期。
  4. 处理异步操作:在处理异步操作时,注意在组件卸载时取消未完成的请求,避免内存泄漏。
  5. 性能优化:对于性能敏感的操作,确保合理使用 useEffect,避免过度渲染和不必要的副作用执行。

推荐:JavaScript


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1958742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

playbooks 分布式部署 LNMP

1、环境配置 ansible 服务器 192.168.10.10nginx 服务器 192.168.10.20mysql 服务器 192.168.10.21php 服务器 192.168.10.22 2、安装 ansble #192.168.10.10节点 yum install -y epel-release #先安装 epel 源 yum install -y ansible配置主机清单 …

Vue 动态改变css文件

theme: smartblue 一、背景需求 现有 Vue3 项目&#xff0c;要求点击按钮后&#xff0c;会动态加载css文件内容 二、实现过程 2.1 相关代码 假设有 blue.css 和 red.css,要求点击加载对应文件 若想切换为原版样式&#xff0c;点击 back 回退到初始样式 this is a simple text …

76.SAP ME - 归档

目录 1.归档 2.系统设置维护 3.后台处理执行 1.归档 可使用此功能将某一特定已完成产品的相关记录从活动的“在制品”(WIP) 数据库移动到归档数据库&#xff0c;这样可改进生产记录的检索。在一段时间内&#xff0c;WIP 数据库中的记录数量将增加。当系统在大量记录中进行搜…

c++ 内存管理(newdeletedelete[])

因为在c里面新增了类&#xff0c;所以我们在有时候会用malloc来创建类&#xff0c;但是这种创建只是单纯的开辟空间&#xff0c;没有什么默认构造的。同时free也是free的表面&#xff0c;如果类里面带有指针指向堆区的成员变量就会free不干净。 所以我们c增加了new delete和de…

pdf太大怎么压缩大小?这几种压缩方法操作起来很简单!

pdf太大怎么压缩大小&#xff1f;在数字化洪流席卷的当下&#xff0c;PDF文件的“臃肿”难题如同巨石般横亘于高效办公之路&#xff0c;它们不仅贪婪地吞噬着宝贵的存储空间&#xff0c;更如沉重的枷锁&#xff0c;拖曳着我们的工作进度&#xff0c;步入迟缓之境&#xff0c;试…

06 内置的整数、实数与复数

在 Python 中&#xff0c;内置的数字类型有整数、实数和复数&#xff0c;借助于标准库 fractions 中的 Fraction 对象可以实现分数及其运算&#xff0c;而 fractions 中的 Decimal 类则实现了更高精度的运算。 Python 支持任意大的数字&#xff0c;具体可以大到什么程度仅受内…

电阻液冷 可提升 3.3kV 中压负载-EAK水冷电阻器

电阻液冷 可提升 3.3kV 中压负载-EAK水冷电阻器 在工业和海洋应用中&#xff0c;水冷在削减电阻器封装方面至关重要的地方 在起重机、升降机、升降机和输送机等电机驱动应用中&#xff0c;风冷电阻器很常见&#xff0c;但在中压、高功率应用中&#xff0c;液体冷却胜出。 使…

IDEA项目的依赖(pom.xml文件)导入问题及解决

前言&#xff1a;该文章为转载&#xff0c;没有仔细的看 IDEA新建项目和pom.xml文件被修改时&#xff0c;右下角都会出现 Maven projects need to be imported&#xff08;项目需要导入依赖&#xff09; 如下&#xff0c;点击 Import Changes导入后&#xff0c;有时会一直处于…

【基础篇】Docker 概览 ONE

嗨&#xff0c;大家好&#xff01;我是小竹笋&#xff0c;一名热爱创作的工程师。今天我将带领大家一起踏上探索 Docker 的奇妙之旅。我们先从 Docker 的历史和发展说起&#xff0c;然后再看看 Docker 和虚拟机之间的区别&#xff0c;最后了解一下 Docker 在各行各业的应用情况…

数据结构算法经典题目刨析(c语言)返回单链表的倒数第 k 个节点

&#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏&#xff1a;数据结构经典题目刨析(c语言) 一.题目描述 二.解题思路 方法一:计数器方式 先遍历链表&#xff0c;求出链表长度count倒数第k个节点&#xff0c;就是正数第count-k1个节点&#xff08;下标为count…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-02-表现层框架设计

文章目录 1. 表现层设计模式1.1 MVC模式1.1.1 三个核心模块1&#xff09;控制器 (Controller)2&#xff09;模型 (Model)3&#xff09;视图 (View): 1.1.2 过程1.1.3 优点1.1.4 应用 1.2 MVP模式1.3 MVVM模式 2. 使用XML设计表现层统一Web Form与 Windows Form的外观3. 表现层中…

⚠️ Buffer Overflow: 安全编码必备知识 ️

⚠️ Buffer Overflow: 安全编码必备知识 &#x1f6e1;️ ⚠️ Buffer Overflow: 安全编码必备知识 &#x1f6e1;️摘要引言正文内容一、缓冲区溢出基本概念 &#x1f9e9;二、常见场景及实际案例 &#x1f6e0;️2.1 利用不安全的函数2.2 堆溢出攻击 三、调试技巧 &#x1f…

算法入门:Java实现排序、查找算法

链接&#xff1a;算法入门&#xff1a;Java实现排序、查找算法 (qq.com) 冒泡/选择/插入/希尔排序代码 (qq.com) 快排/归并/堆排/基数排序代码 (qq.com)

Python酷库之旅-第三方库Pandas(053)

目录 一、用法精讲 196、pandas.Series.first方法 196-1、语法 196-2、参数 196-3、功能 196-4、返回值 196-5、说明 196-6、用法 196-6-1、数据准备 196-6-2、代码示例 196-6-3、结果输出 197、pandas.Series.head方法 197-1、语法 197-2、参数 197-3、功能 1…

【C++题解】1069. 字符图形5-星号梯形

问题&#xff1a;1069. 字符图形5-星号梯形 类型&#xff1a;嵌套循环、图形输出 题目描述&#xff1a; 打印字符图形。 输入&#xff1a; 一个整数&#xff08; 0<n<10 &#xff09;。 输出&#xff1a; 一个字符图形。 样例&#xff1a; 输入&#xff1a; 3输…

卷积神经网络(三)---案例分析

上面部分介绍了 PyTorch 中的卷积模块&#xff0c;接下来将会介绍几个卷积神经网络的案例&#xff0c;通过案例入手来介绍卷积神经网络的结构设计。 1. LeNet LeNet 是整个卷积神经网络的开山之作&#xff0c;1998年由 LeCun 提出&#xff0c;它的结构特别简单&#xff0c;我们…

看懂循环队列

循环队列的设计过程 1.循环队列2.设计循环队列的逻辑过程2.1 定义循环队列的数据结构2.2 初始化队列2.3 入队操作2.4. 出队操作2.5 判断队列状态2.5 获取队头和队尾的元素力扣相关题目完整代码 1.循环队列 循环队列是使用有限数组来模拟队列&#xff0c;与普通的队列不同的是&…

文献综述在确定先前研究中使用的方法学方法方面发挥什么作用

VersaBot一键生成文献综述 文献综述在确定先前研究中使用的方法学方法方面发挥着至关重要的作用&#xff0c;可以作为设计自己的方法论并证明其重要性的基础。就是这样; 1. 揭示现有方法&#xff1a; 通过探索与您的主题相关的研究&#xff0c;您将发现其他研究人员采用的不同…

普通人有必要学Python吗?学了之后能做什么?

目录 首先来说一下极其推荐的方向&#xff1a; 1、数据分析 2、科学计算 3、大数据框架 4、脚本开发 5、爬虫 6、Web框架 总结&#xff1a; 如果你还没有开始使用Python&#xff0c;答应我&#xff0c;把这个回答看完&#xff0c;如果你真的学习并深入使用过Python&…