useEffect的第二个参数

目录

1、第一个参数:

 2、第二个参数:

2.1  不传值:无限循环

2.2  空数组作为依赖:执行一次

2.3  基本类型作为依赖:无限循环

2.4  引用类型

2.4.1  数组作为依赖:无限循环

  2.4.2  函数作为依赖:无限循环

  2.4.3  对象作为依赖:无限循环


1、第一个参数:

        是一个函数,必传项。是组件要执行的副作用。可以看做componentDidMountcomponentDidUpdate 和 componentWillUnmount 这三个函数的组合。

const [count, setCount] = useState(0);useEffect(() => {// 普通函数,执行副作用,可以实现componentDidMount、componentDidUpdateconsole.log('执行副作用');   // return函数, 组件销毁时清除副作用,可以实现componentWillUnmountreturn () => {            console.log("清除副作用");};
}, [count]);

 2、第二个参数:

        可以不传或者是一个数组,非必传项。数组里面依赖改变时候副作用函数才会重新更新。

所谓依赖改变就是  对比 [ 之前值 === 之后值 ] ,如果为true不执行useEffect,为false重新执行useEffect

第二个参数类型:不传、[]、由基本类型或者引用类型组成的数组

2.1  不传值:无限循环

【现象】: useEffectuseEffectuseEffect 会在第一次渲染以及每次更新渲染后都执行

原因

        第一次渲染后执行一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect没有比较值,useEffect重新执行,useEffect中回调函数改变state值,state值改变触发组件重新渲染,无限循环

注意:不传值是一种缺失依赖关系的情况,不建议这么做。

const [count, setCount] = useState<number>(1);
useEffect(() => {setTimeout(() => {setCount(count + 1);}, 1000);console.log(`第二个参数: 不传值, 第 ${count} 次执行`);
});// 打印log,无限循环
第二个参数: 不传值, 第 1 次执行
第二个参数: 不传值, 第 2 次执行
第二个参数: 不传值, 第 3 次执行
第二个参数: 不传值, 第 ... 次执行

2.2  空数组作为依赖:执行一次

【现象】: useEffect 会在第一次渲染后执行一次

【原因】: 第一次渲染后执行一次一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect中 [] 没有值,依赖没变,不触发useEffect,不执行回调函数, state 无更新,不触发组件重新渲染,至此结束

const [count, setCount] = useState<number>(1);
useEffect(() => {setTimeout(() => {setCount(count + 1);}, 1000);console.log(`第二个参数: 空数组, 第 ${count} 次执行`);
}, []);// 打印log,执行一次
第二个参数: 空数组, 第 1 次执行

2.3  基本类型作为依赖:无限循环

基本类型有:整型、浮点型、布尔型(true,false)、字符型、字符串、空值或null(Null)

【现象】: useEffect 会在第一次渲染以及每次更新渲染后都执行。

【原因】: 第一次渲染后执行一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect比较值(count)改变,useEffect重新执行,useEffect中回调函数改变state值,state值改变触发组件重新渲染,无限循环。

注意:传入第二个参数,只有一个值,比较该值有变化就执行,如果有多个值的数组,会比较每一个值,有一个变化就执行

const [count, setCount] = useState<number>(1);  // 基本类型以number为例
useEffect(() => {setTimeout(() => {setCount(count + 1);}, 1000);console.log(`第二个参数: 基本类型, 第 ${count} 次执行`);
}, [count]);// 打印log,无限循环
第二个参数: 基本类型, 第 1 次执行
第二个参数: 基本类型, 第 2 次执行
第二个参数: 基本类型, 第 3 次执行
第二个参数: 基本类型, 第 ... 次执行

2.4  引用类型

2.4.1  数组作为依赖:无限循环

【现象】useEffect 会在第一次渲染以及每次更新渲染后都执行。

【原因】:第一次渲染后执行一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect依赖项arr发生变化,此处依赖数组执行浅层比较[...] === [...] 为false)useEffect重新执行,useEffect中回调函数改变state值,state值改变触发组件重新渲染,无限循环

const [count, setCount] = useState(1);
const newArr = [4,5];
useEffect(() => {setTimeout(() => {setCount(count+1);}, 1000);console.log(`第二个参数: 数组, 第 ${count} 次执行`);
}, [newArr]);// 打印log,无限循环
第二个参数: 数组, 第 1 次执行
第二个参数: 数组, 第 2 次执行
第二个参数: 数组, 第 3 次执行
第二个参数: 数组, 第 ... 次执行

【测试】去除setTimeout会出现什么情况?---无限循环

        因为useEffect频繁调用setState,state不断改变

const [count, setCount] = useState(1);
const newArr = [4,5];
useEffect(() => {setCount(count+1);console.log(`第二个参数: 基本类型, 第 ${count} 次执行`);
}, [newArr]);// 打印log报错,说:超出最大更新深度

【解决】 使用useRef,useRef会在每次渲染时返回同一个ref对象,返回的ref在组件的整个生命周期内保持不变

const [count, setCount] = useState(1);
const refArr = useRef([4, 5, 6]);
useEffect(() => {setCount(count+1);console.log(`第二个参数: 数组, 第 ${count} 次执行`);
}, [refArr.current]);// 打印log,执行一次
第二个参数: 数组, 第 1 次执行

  2.4.2  函数作为依赖:无限循环

【现象】useEffect 会在第一次渲染以及每次更新渲染后都执行。

【原因】:第一次渲染后执行一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect依赖项consoleFunction函数发生变化,此处依赖函数执行浅层比较(每次渲染都重新创建一个新的函数 function(前) === function(后)为false)useEffect重新执行,useEffect中回调函数改变state值,state值改变触发组件重新渲染,无限循环

const [count, setCount] = useState(1);
const consoleFunction = () => {console.log('consoleFunction');
};
useEffect(() => {setTimeout(() => {setCount(count + 1);}, 1000);console.log(`第二个参数: 函数, 第 ${count} 次执行`);
}, [consoleFunction]);// 打印log,无限循环
第二个参数: 函数, 第 1 次执行
第二个参数: 函数, 第 2 次执行
第二个参数: 函数, 第 3 次执行
第二个参数: 函数, 第 ... 次执行

【测试】去除setTimeout会出现什么情况?---无限循环

        因为useEffect频繁调用setState,state不断改变

        打印报错:“ 超出最大更新深度 ”

【解决】: 使用useCallback,useCallback返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新

const [count, setCount] = useState(1);
const consoleFunction = useCallback(() => {console.log('consoleFunction');
}, []);
useEffect(() => {setCount(count + 1);console.log(`第二个参数: 函数, 第 ${count} 次执行`);
}, [consoleFunction]);// 打印log,执行一次
第二个参数: 函数, 第 1 次执行

  2.4.3  对象作为依赖:无限循环

【现象】useEffect 会在第一次渲染以及每次更新渲染后都执行。

【原因】:第一次渲染后执行一次useEffect,useEffect中回调函数改变state值,state值改变触发组件重新渲染,useEffect依赖项obj发生变化,此处依赖对象执行浅层比较( {...}=== {...} 为false)useEffect重新执行,useEffect中回调函数改变state值,state值改变触发组件重新渲染,无限循环

const [count, setCount] = useState(1);
const obj = {name: 'zhangsan'};
useEffect(() => {setTimeout(() => {setCount(count + 1);}, 1000);console.log(`第二个参数: 对象, 第 ${count} 次执行`);
}, [obj]);// 打印log,无限循环
第二个参数: 对象, 第 1 次执行
第二个参数: 对象, 第 2 次执行
第二个参数: 对象, 第 3 次执行
第二个参数: 对象, 第 ... 次执行

【测试】去除setTimeout会出现什么情况?---无限循环

        因为useEffect频繁调用setState,state不断改变

        打印报错:“ 超出最大更新深度 ”

【解决】: 使用useMemo,useMemo该回调函数仅在某个依赖项改变时才会更新。此处使用[ ]依赖,组件重新渲染后对象不再重新定义

const [count, setCount] = useState(1);
const obj = useMemo(() => ({name: 'zhangsan'}), []);
useEffect(() => {setCount(count + 1);console.log(`第二个参数: 对象, 第 ${count} 次执行`);
}, [obj]);// 打印log
第二个参数: 对象, 第 1 次执行

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

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

相关文章

MySQL备份和恢复(二)mysqldump

注意&#xff1a;mysqldump是完全备份 一、mysqldump备份命令 1、 备份数据库 含创建库语句 &#xff08;1&#xff09;备份指定数据库 完全备份一个或多个完整的库&#xff0c; mysqldump -uroot -p[密码] --databases 库名1 [库名2].. >/备份路径/备份文件名.sql#导出…

溯源取证-iphone取证-高难度篇

摘要&#xff1a; 本次内容主要讲解iphone8取证&#xff0c;算是年前最后一篇了&#xff0c;大家将就着看哈 本次使用的工具&#xff1a; ileappGUI.exe github一款开源且免费的移动介质取证工具 Magnet Axiom Cyber 一款付费的移动介质取证工具 DB.Browser.for.SQLite-3.12…

【Node.js基础】Node.js的介绍与安装

文章目录 前言一、什么是Node.js&#xff1f;二、安装Node.js2.1 Windows系统2.2 macOS系统2.3 Linux系统 三、运行js代码总结 前言 随着互联网技术的不断发展&#xff0c;构建高性能、实时应用的需求日益增长。Node.js作为一种服务器端运行时环境&#xff0c;以其事件驱动、非…

遍历删除空文件夹

文章目录 遍历删除空文件夹概述笔记END 遍历删除空文件夹 概述 在手工整理openssl3.2编译完的源码工程中的文档, 其中有好多空文件夹. 做了一个小工具, 将空文件夹都遍历删除掉. 这样找文档方便一些. 删除后比对了一下, 空文件夹还真不少. 笔记 // EmptyDirRemove.cpp : 此…

力扣hot100 数组中的第K个最大元素 堆 三路划分

Problem: 215. 数组中的第K个最大元素 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( log ⁡ n ) O(\log{n}) O(logn) Code class Solution {public int findKthLargest(int[] nums, int k…

数据结构--堆排序(超详细!)

一、前言 堆排序与Top K问题是堆的两大应用&#xff0c;在我们日常也有很广泛的用处 我们已经上面已经说过了堆&#xff0c;这次来说堆的其中一个应用---堆排序。 二、堆排序 堆排序优势在哪里&#xff1f;有什么恐怖之处吗&#xff1f; 重点&#xff1a;拿一个举例&…

Java项目要不要部署在Docker里?

部署Java项目有很多种方式&#xff0c;传统的方式是直接在物理机或虚拟机上部署应用&#xff0c;但为什么现在容器化部署变得越来越流行&#xff0c; 个人觉得原因有以下几个&#xff1a; 1、 环境一致性&#xff1a;使用Docker可以确保开发、测试和生产环境的一致性&#xff…

使用libtorch实现sobel算子进行边缘检测,python和c++实现

文章目录 pythonpython结果 cppc结果 python import torch import torch.nn as nn from PIL import Image import numpy as np import cv2class SobelEdgeDetector(nn.Module):def __init__(self):super(SobelEdgeDetector, self).__init__()self.convx nn.Conv2d(1,1,3,padd…

植物病害检测YOLOV8,OPENCV调用

【免费】植物病害检测&#xff0c;10种类型&#xff0c;YOLOV8训练&#xff0c;转换成ONNX&#xff0c;OPENCV调用资源-CSDN文库 植物病害检测&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTH…

实现vue3响应式系统核心-shallowReactive

简介 今天来实现一下 shallowReactive 这个 API。 reactive函数是一个深响应&#xff0c;当你取出的值为对象类型&#xff0c;需要再次调用 reactive进行响应式处理。很明显我们目前的代码是一个浅响应&#xff0c;即 只代理了对象的第一层&#xff0c;也就是 shallowReactiv…

【java核心-IoC(控制反转)和DI(依赖注入)及AOP(面向切面编程)】

java核心-IoC&#xff08;控制反转&#xff09;和DI&#xff08;依赖注入&#xff09;及AOP&#xff08;面向切面编程&#xff09; 控制反转&#xff08;IoC&#xff09;依赖注入&#xff08;DI&#xff09;面向切面编程&#xff08;AOPAOP的应用场景包括但不限于&#xff1a;以…

安装和启动berTopic,hdbscan和importlib.metadata

1. 安装问题&#xff1a;hdbsacn 安装berTopic的时候&#xff0c;包 hdbsacn一直安装失败&#xff0c;报出以下错误&#xff1a; 尝试了很多办法&#xff1a;① 下载hdbscan的tar.gz文件安装&#xff0c;安装失败&#xff1b;② 安装*.whl文件&#xff0c;安装成功&#xff…