Effect Hook

  • 清除 effect
  • 多个effect
  • 跳过 Effect

今天学习另一个 Hook: useEffect,它能在函数组件中执行副作用,与 class 中的生命周期函数极为类似。

useEffect Hook 可以看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。

例子:

import React, { useState, useEffect } from 'react'
function Example () {const [count, setCount] = useState(0)const [age, setAge] = useState(42)useEffect(() => {// 将 document 的 title 设置为包含了点击次数的消息document.title = `You clicked ${count} times`;});return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button><p>setAge: {age} </p><button onClick={() => setAge(age + 3)}>Click me</button></div>)
}
export default Example

等价于:

import React from 'react'class Example extends React.Component {constructor(props) {super(props);this.state = {count: 0,age: 10};}componentDidMount () {document.title = `You clicked ${this.state.count} times`;}componentDidUpdate () {document.title = `You clicked ${this.state.count} times`;}render () {return (<div><p>You clicked {this.state.count} times</p><button onClick={() => this.setState({count: this.state.count + 1})}>Click me</button><p>setAge: {this.state.age} </p><button onClick={() => this.setState({age: this.state.age + 3})}>Click me</button></div>);}
}
export default Example

页面效果:

在 effect 中可以直接访问 count state 变量(或其他 props),它已经保存在函数作用域中。(Hook 使用了 JavaScript 的闭包机制)
默认情况下,effect 在第一次渲染之后和每次更新之后都会执行。effect 发生在“渲染之后”,可以不用再去考虑“挂载”还是“更新”。
当 React 渲染组件时,会保存已使用的 effect,并在更新完 DOM 后执行它。每次重新渲染,都会生成新的 effect,替换掉之前的。(也就是说,每个 effect “属于”一次特定的渲染)

清除 effect

如果 effect 返回一个函数,React 将会在执行清除操作时调用它。

每个 effect 都可以返回一个清除函数,可以将添加和移除订阅的逻辑放在一起。它们都属于 effect 的一部分。 React 会在组件卸载的时候执行清除操作。

例子:

  useEffect(() => {document.title = `You clicked ${count} times`;return () => {// 执行清除操作}})

不必做清除操作的 effect 所以不需要返回函数,例如:

 useEffect(() => {document.title = `You clicked ${count} times`;});

多个effect

Hook 允许按照代码的用途分离他们, 而不是像生命周期函数那样。

useEffect(() => {document.title = `You clicked ${count} times`;
})
useEffect(() => {console.log('倒计时完毕!')
})

React 将按照 effect 声明的顺序依次调用组件中的每一个 effect。

跳过 Effect

如果某些特定值在两次重渲染之间没有发生变化,可以通知 React 跳过对 effect 的调用,只要传递数组作为 useEffect 的第二个可选参数即可:

  useEffect(() => {// 将 document 的 title 设置为包含了点击次数的消息document.title = `You clicked ${count} times`;}, [count]) // 仅在 count 更改时更新

上面这个例子中,传入 [count] 作为第二个参数,来实现性能优化。

具体实现:

如果 count 的值是 5,而且组件重渲染的时候 count 还是等于 5,React 将对前一次渲染的 [5] 和后一次渲染的 [5] 进行比较。因为数组中的所有元素都是相等的(5 === 5),React 会跳过这个 effect,这就实现了性能的优化。

例子:

import React, { useState, useEffect } from 'react';let timer; //声明定时器const Example = () => {const [current, setCurrent] = useState(0)const [time, setTime] = useState(5)useEffect(() => {return () => {clearInterval(timer)}}, [])// 想执行只运行一次的 effect(仅在组件挂载和卸载时执行),传递一个空数组([])作为第二个参数。// 告诉 React,effect 不依赖于 props 或 state 中的任何值,永远都不需要重复执行。useEffect(() => {if (current === 1) {runTimerJump()}}, [current])useEffect(() => {if (time === 0) {clearInterval(timer)setTime(5)alert('倒计时完毕!')console.log('倒计时完毕!')}}, [time])const runTimerJump = () => {timer = setInterval(() => setTime(t => --t), 1000)}return (<><p><span>{time}s 后执行对应的操作</span><br /></p><p><button onClick={() => setCurrent(1)}>点击开启</button></p></>)
}
export default Example

页面效果:

以上例子中,useEffect中 的 return 是返回来一个函数,来清除定时器:

useEffect(() => {return () => {clearInterval(timer)}}, [])// 想执行只运行一次的 effect(仅在组件挂载和卸载时执行),传递一个空数组([])作为第二个参数。// 告诉 React,effect 不依赖于 props 或 state 中的任何值,永远都不需要重复执行。

传递一个空数组([])作为第二个参数,effect 内部的 props 和 state 会一直拥有其初始值,告诉 React,effect 不依赖于 props 或 state 中的任何值,永远都不需要重复执行。

适用情形:想执行只运行一次的 effect(仅在组件挂载和卸载时执行)。

Hook 学习系列(二) —— Effect Hook相关推荐

  1. 图机器学习(GML)图神经网络(GNN)原理和代码实现(前置学习系列二)

    图机器学习(GML)&图神经网络(GNN)原理和代码实现(PGL)[前置学习系列二] 上一个项目对图相关基础知识进行了详细讲述,下面进图GML networkx :NetworkX 是一个 P ...

  2. Linux学习系列二:Linux中的常用命令

    这个系列的Linux教程主要参考刘遄老师的<Linux就该这么学>.用的系统是RHEL8,如果遇见一些命令出现问题,请首先检查自己的系统是否一致,如果不一致,可网上查一下系统间某些命令之间 ...

  3. Pyside2 学习系列二:PyInstaller打包项目exe (超详细的Pyside2 攻略)

    继上一篇文章创建了项目后,本章我们进行项目的打包工作. 本项目的所有演示代码:github可在这里下载. 打包只用的工具为PyInstaller. 打包步骤 1 准备环境 1.1 安装`PyInsta ...

  4. A.图机器学习(GML)图神经网络(GNN)原理和代码实现(前置学习系列二)

    图学习图神经网络算法专栏简介:主要实现图游走模型(DeepWalk.node2vec):图神经网络算法(GCN.GAT.GraphSage),部分进阶 GNN 模型(UniMP标签传播.ERNIESa ...

  5. hook修改信息_React系列二十一 Hook(二)高级使用

    一. Hook高级使用 1.1. useReducer 很多人看到useReducer的第一反应应该是redux的某个替代品,其实并不是. useReducer仅仅是useState的一种替代方案: ...

  6. RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列

    上一篇已经讲了Rabbitmq如何在Windows平台安装,不懂请移步:RabbitMQ学习系列一:windows下安装RabbitMQ服务 一.理论: .net环境下,C#代码调用RabbitMQ消 ...

  7. HOOK API(二)—— HOOK自己程序的 MessageBox

    0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程序对MessageBox API的调用重定向到自己实现的API中,在自己 ...

  8. Java I/O系统学习系列二:输入和输出

    编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象."流"屏蔽了实际的I/O设备中处理数据的细节. 在这个系列的第一篇 ...

  9. Nginx学习系列二Linux下Nginx实现负载均衡

    关于在本地虚拟机(VMware 14)下安装Linux同时安装Nginx,请参考Nginx学习系列之搭建环境 1.启动Nginx 在Nginx安装成功的前提下,启动Nginx 已root模式登陆(权限 ...

最新文章

  1. java指定位置写入_java指定路径写、读文件
  2. 为啥辣椒会辣得人嘴巴疼?这个问题竟然和今年诺奖有关
  3. Spring boot 梳理 - WebMvcConfigurer接口 使用案例
  4. Linux环境下USB的原理、驱动和配置
  5. 不可摸数http://acm.hdu.edu.cn/showproblem.php?pid=1999
  6. 04.卷积神经网络 W4.特殊应用:人脸识别和神经风格转换(作业:快乐屋人脸识别+图片风格转换)
  7. wow 私服trinitycore
  8. opencore 启动总是在win_OpenCore引导开机倒计时自动进入指定系统盘,修改默认启动项教程...
  9. 海康人脸服务器型号,DS-2CD7A27FWD/F-LZ(S) 海康人脸识别摄像机 海康200万像素深眸智能人脸日夜筒型网络摄像机...
  10. 深信服面试智力题-------三人求平均工资
  11. Python文件指针
  12. Python for S60(pys60)介绍
  13. 2020 ECCV 所有论文及补充材料链接(二)
  14. 王飞跃谈正来临的第五次工业革命:“未来一定有多个平行的你”
  15. Excel 对象模型
  16. ubuntu硬盘扩容
  17. cad 打开硬件加速卡_谁说没有核显就不能开启硬件加速?手把手教你开启加速
  18. 12-1 蓝色天空 : 创建一个背景为蓝色的Pygame窗口 12-2 游戏角色 : 找一幅你喜欢的游戏角色位图图像或将一幅图像转换为位图。 创建一个类, 将该角色绘制到屏幕中央, 并将该图像的背景色
  19. MySQL之——数据库的基本操作
  20. 淘宝框架atlas集成

热门文章

  1. miniUI合并居中详解
  2. opencv--python(一)图像和视频处理之读取,显示和保存
  3. jetty文件服务器,Jetty 服务器
  4. 鸿蒙os系统2k级别屏,华为鸿蒙OS概念新机:90Hz刷新率+全系双模5G+2K屏 这才是华为...
  5. pyQT 视频播放器(三) 实现视频截图、获取每一帧数据
  6. 阿里云轻量应用服务器一键安装ECShop镜像搭建小型电商网站
  7. 基于php的校园失物招领平台系统(自动化匹配招领启事)
  8. html5 video speed control插件,HTML5 Video Speed Control 1.34
  9. UVM Systemverilog EDA IP国外学习网站
  10. 安卓仿写多玩的《英雄联盟盒子》系列源码(一)——效果预览与前言