ReactHooks大全—useEffect

React Hooks是一种在函数组件中使用状态和生命周期等特性的方法。useEffect是其中一个常用的Hook,它可以让你在组件渲染后执行一些副作用操作,比如发送网络请求、订阅事件、修改DOM等。在本文中,我们将介绍useEffect的基本使用、实现原理、最佳实践,并给出一些代码示例。

基本使用

useEffect的基本语法如下:

useEffect(() => {// 在这里执行你的副作用操作return () => {// 在这里执行你的清理操作,比如取消订阅、移除事件监听器等};
}, [deps]);

useEffect接受两个参数,第一个是一个函数,第二个是一个依赖数组。

第一个函数会在每次组件渲染后执行,除非你指定了依赖数组。如果你指定了依赖数组,那么只有当数组中的任何一个值发生变化时,才会执行第一个函数。

如果你想让第一个函数只执行一次,那么你可以传递一个空数组作为依赖数组。第一个函数可以返回一个清理函数,这个清理函数会在组件卸载时或者下一次执行第一个函数之前执行,用于清理上一次的副作用。

下面是一个简单的例子,展示了如何使用useEffect来获取用户的地理位置,并在组件卸载时取消订阅:

import React, { useState, useEffect } from "react";function Location() {const [position, setPosition] = useState({ latitude: 0, longitude: 0 });useEffect(() => {// 创建一个订阅对象const geo = navigator.geolocation.watchPosition((pos) => {// 更新位置状态setPosition({latitude: pos.coords.latitude,longitude: pos.coords.longitude,});},(err) => {// 处理错误console.error(err);});// 返回一个清理函数return () => {// 取消订阅navigator.geolocation.clearWatch(geo);};}, []); // 传递一个空数组,表示只执行一次return (<div><p>Latitude: {position.latitude}</p><p>Longitude: {position.longitude}</p></div>);
}

实现原理

要理解useEffect的实现原理,我们需要先了解一下React的渲染机制。

React使用了一种叫做Fiber的数据结构来表示组件树,每个Fiber节点都对应一个组件实例,包含了该组件的类型、状态、属性、子节点等信息。

React在渲染组件时,会遍历Fiber树,创建或更新对应的DOM节点,这个过程叫做渲染阶段。在渲染阶段,React可能会因为优先级或其他原因而中断或重启渲染,所以这个阶段是可以被打断的。在渲染阶段结束后,React会进行提交阶段,在这个阶段,React会将渲染的结果应用到DOM上,这个阶段是不可被打断的。

useEffect的执行时机就是在提交阶段之后,也就是说,当组件已经渲染到DOM上后,才会执行useEffect的回调函数。

这样做的好处是,避免在渲染阶段执行可能导致副作用的操作,比如修改DOM、发送网络请求等,这些操作可能会影响组件的渲染性能或造成不一致的状态。

另外,这样也可以保证useEffect的回调函数总是能获取到最新的状态和属性,因为它们已经被同步到DOM上了。

那么,React是如何实现useEffect的呢?其实,React在渲染组件时,会收集所有的useEffect回调函数,并将它们存放在一个队列中,然后在提交阶段结束后,依次执行这个队列中的回调函数。

同时,React也会收集所有的清理函数,并将它们存放在另一个队列中,然后在组件卸载时或者下一次执行相应的useEffect回调函数之前,依次执行这个队列中的清理函数。这样,React就实现了useEffect的基本功能。

但是,这还不够,因为useEffect还有一个依赖数组的参数,它可以控制useEffect的回调函数是否需要执行。为了实现这个功能,React在渲染组件时,会比较当前的依赖数组和上一次的依赖数组,如果它们不相同,那么就会将对应的useEffect回调函数放入队列中,否则就会跳过它。这里的比较是使用Object.is算法,也就是说,只有当依赖项的值严格相等时,才会认为它们没有变化。

这意味着,如果依赖项是一个对象或一个数组,那么即使它们的内容没有变化,但是每次都重新创建,也会导致useEffect重新执行。因此,建议使用useCallbackuseMemo来缓存这些依赖项,避免每次都重新创建。

这样,React就可以根据依赖数组来优化useEffect的执行效率,避免不必要的副作用操作。

最佳实践

使用useEffect时,有一些最佳实践可以遵循,以提高代码的可读性、可维护性和性能。下面列举了一些常见的最佳实践:

  • 尽量将不同的副作用操作分开,使用多个useEffect,而不是将所有的副作用操作放在一个useEffect中。这样可以让代码更清晰,也可以让React更好地优化useEffect的执行。
  • 尽量指定依赖数组,而不是省略它。如果省略了依赖数组,那么useEffect的回调函数会在每次渲染后都执行,这可能会导致性能问题或不一致的状态。如果你想让useEffect的回调函数只执行一次,那么你可以传递一个空数组作为依赖数组。
  • 尽量将依赖数组中的值保持稳定,而不是每次都重新创建。如果依赖数组中的值每次都变化,那么useEffect的回调函数也会每次都执行,这可能会导致性能问题或不一致的状态。如果你需要依赖一个函数或一个对象,那么你可以使用useCallback或useMemo来缓存它们,避免每次都重新创建。
  • 尽量在useEffect的回调函数中返回一个清理函数,用于清理副作用操作,比如取消订阅、移除事件监听器等。这样可以避免内存泄漏或其他问题。
  • 尽量避免在useEffect的回调函数中修改状态或属性,因为这可能会导致无限循环或其他问题。如果你需要根据副作用操作来修改状态或属性,那么你可以使用setState或useReducer来异步地更新它们,避免直接修改它们。

总结

useEffectReact Hooks中一个非常强大和灵活的Hook,它可以让你在函数组件中执行各种副作用操作,比如发送网络请求、订阅事件、修改DOM等。在使用useEffect时,你需要注意它的执行时机、依赖数组、清理函数等细节,以及遵循一些最佳实践。

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

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

相关文章

Note3---初阶二叉树~~

目录​​​​​​​ 前言&#x1f344; 1.树概念及结构☎️ 1.1 树的概念&#x1f384; 1.2 树的相关概念&#x1f99c; 1.2.1 部分概念的加深理解&#x1f43e; 1.2.2 树与非树&#x1fab4; 1.3 树的表示&#x1f38b; 1.4 树在实际中的运用&#xff08;表示文件系统…

[Onnx简化库深度剖析] OnnxSimplifier和OnnxOptimizer解读-(2)

[Onnx简化库深度剖析] OnnxSimplifier和OnnxOptimizer解读-(2) 简介 上篇重点介绍了OnnxSimplifier的库&#xff0c;其中的FixedPointFn迭代优化函数利用到了OnnxOptimizer这个官方的优化库&#xff0c;大部分的优化细节是在OnnxOptimizer内的。因此本篇重点介绍一下OnnxOpti…

飞天使-docker知识点12-docker-compose

文章目录 docker-compose命令启动单个容器重启容器停止和启动容器停止和启动所有容器演示一个简单示范 docker-compose 部署有依赖问题 Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。它允许您使用简单的 YAML 文件来配置应用程序的服务、网络和存储等方…

全志V3s之NFS连接ubuntu22.04

1、问题一&#xff1a; [ 100.329728] VFS: Unable to mount root fs via NFS, trying floppy. [ 100.336262] VFS: Cannot open root device "nfs" or unknown-block(2,0): error -6 [ 100.343580] Please append a correct "root" boot option; here…

RT-Smart elf 动态加载技术 : 开启 ldso 动态加载

前言 RT-Smart,类似于Linux,可以动态的加载运行 应用程序 elf 文件 应用程序 elf 文件,有的是静态链接编译的,有的是动态链接编译的,动态链接编译的,还需要加载 动态共享库 (.so) 本篇讲解一下 RT-Smart 上 elf 动态加载功能的实现,顺便讲一下动态加载的原理 环境搭建 R…

12.18

有道云笔记 机械臂 #include <myhead.h> #define SERPORT 8822 #define SERIP "192.168.125.61" #define PORT 6666 #define IP "192.168.125.88" int main(int argc, const char *argv[]) {int cfd-1;if((cfdsocket(AF_INET,SOCK_STREAM,0))-1){p…

RTrPPG

研究背景 心率 (HR) 和脉搏率变异性 (PRV) 是允许分析心脏行为的两个生理参数。心率监测可以通过接触式和非接触式的两种方法进行。通常用于测量 HR 和 PRV 的两种接触式技术是心电图 (ECG) 和光电容积脉搏波 (PPG)。 ECG 测量由心脏活动引起的电场。另一方面&#xff0c;PPG …

02什么是CPU上下文切换

上⼀节&#xff0c; 讲了要怎么理解平均负载&#xff08; Load Average&#xff09; &#xff0c; 并⽤三个案例展示了不同场景下平均负载升⾼的分析⽅法。 这其中&#xff0c; 多个进程竞争 CPU 就是⼀个经常被我们忽视的问题。 1、CPU上下文切换的概念 我想你⼀定很好奇&am…

2023/12/18 work

1. 机械臂 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <myhead.h>#define CLI_PORT 6667 //本机的端口号 #define CLI_IP "192.168.125.79" //本机的IP#define SER_PORT 8888 //服务器的端口号 #define…

智能家居和智能家居控制设备有什么区别?

智能家居和智能家居控制设备在功能和用途伤的区别&#xff1a; 智能家居是一种整体的概念&#xff0c;它涵盖了整个家庭环境的智能化&#xff0c;包括智能家电、智能照明、智能安防等设备的互联互通和协同工作。智能家居的目标是通过中央控制器或智能音箱等设备&#xff0c;实现…

瑞安籍侨领池万进荣任意大利瑞安同乡总会第五届会长

浙江温州瑞安是全国重点侨乡&#xff0c;拥有海外侨胞16万人、侨领2100多名、归侨侨眷近12万人&#xff0c;在世界100多个国家和地区建有70多个侨团组织。 意大利瑞安同乡总会第五届理事会会长团全体成员 青年部全体成员 各兄弟会长及代表 12月10日&#xff0c;意大利瑞安同乡…

LabVIEW在燃气轮机发电机组励磁控制系统测试中的应用

LabVIEW在燃气轮机发电机组励磁控制系统测试中的应用 燃气轮机发电机组作为一种高效可靠的常备应急电源&#xff0c;在保障发电品质稳定性和可靠性方面发挥着关键作用。其中&#xff0c;励磁控制系统是保证供电质量的重要环节&#xff0c;对发电机组的稳定运行至关重要。为了有…

渲染函数JSX

大多数情况使用vue模板语法创建应用&#xff0c;在某些场景下&#xff0c;需要用到JavaScript完全的编程能力&#xff0c;这时就用到渲染函数了。 基本用法 创建Vnodes Vue提供了一个h()函数用于创建vnodes&#xff1a; import {h} from vueconst vnode h(div, // type{ i…

档案数字化管理可以提供什么服务?

档案数字化管理提供了便捷、高效和安全的档案管理服务&#xff0c;帮助组织更好地管理和利用自己的档案资源。 具体来说&#xff0c;专久智能档案数字化管理可以提供以下服务&#xff1a; 1. 档案扫描和数字化&#xff1a;将纸质档案通过扫描仪转换为数字格式&#xff0c;包括文…

xtu oj 1293 Diamond

题目描述 根据给出的尺寸n输出一个字符钻石&#xff0c;比如n3时&#xff0c;字符钻石为 CCBC CBABCCBCC 输入 第一行是整数K&#xff0c;表示样例的个数。 以后每行一个样例&#xff0c;为钻石的尺寸&#xff0c;n(1≤n≤26) 输出 依次输出每个样例的结果&#xff0c;每个…

Peter算法小课堂—简单建模(4)

太戈编程1655题 一条直线上&#xff0c;你安排了n个哨兵站岗放哨&#xff0c;编号从1到n。其中i号哨兵的坐标位置是x[i]。不会有哨兵站在相同的位置。作为指挥官&#xff0c;你需要知道3个信息&#xff1a; 1.从左到右&#xff0c;每个哨兵的坐标依次是几? 2.从左到右&…

当抖店有订单支付或确认时,无需人工操作,通过自动化流程实现自动解密电话号码并发送引流短信,高效转化私域用户

1 场景描述 为了提高用户体验&#xff0c;越来越多的企业正转向使用抖音小店来销售产品或扩大其粉丝群。在线教育行业尤其倾向于以抖店为其主要销售平台。这些公司通常会在抖店上销售试听课程&#xff0c;并通过抖店获取的用户手机号码发送短信&#xff0c;进而将潜在客户引导到…

uniapp蓝牙

在 uni-app 中开发蓝牙相关的小程序涉及到使用 uni-app 提供的蓝牙 API。uni-app 为多端开发提供了统一的 API&#xff0c;这意味着你编写的代码可以在不同的平台上运行&#xff0c;包括微信小程序。 以下是实现蓝牙功能的基本步骤和代码示例&#xff1a; 1. 开启蓝牙适配器 …

开发企业展示小程序的关键步骤和技巧

随着移动互联网的快速发展&#xff0c;小程序已经成为企业展示形象、推广产品和服务的重要工具。拥有一个优秀的小程序可以帮助企业提高品牌知名度&#xff0c;吸引更多潜在客户&#xff0c;提升用户体验。以下是拥有一个展示小程序的步骤&#xff1a; 确定需求和目标 首先&am…

【深度学习】序列生成模型(二):束搜索

文章目录 序列生成束搜索理论基础算法步骤python实现 序列生成 在进行最大似然估计训练后的模型 p θ ( x ∣ x 1 : ( t − 1 ) ) p_\theta(x | \mathbf{x}_{1:(t-1)}) pθ​(x∣x1:(t−1)​)&#xff0c;我们可以使用该模型进行序列生成。生成的过程是按照时间顺序逐步生成序…