useEffect与useLayoutEffect

useEffectuseLayoutEffect可以统称为Effect HookEffect Hook可以在函数组件中执行副作用操作,副作用是指函数或者表达式的行为依赖于外部环境,或者在这里可以理解为修改了某状态会对其他的状态造成影响,这个影响就是副作用,数据获取,设置订阅以及手动更改React组件中的DOM都属于副作用。

useEffect

useEffect Hook可以看做 componentDidMountcomponentDidUpdatecomponentWillUnmount这三个生命周期函数的组合,但是使用多个Effect实现关注点分离,也就是说useEffect的粒度更低,可以将各个关注的位置分离处理副作用。

既然是对componentDidMountcomponentDidUpdatecomponentWillUnmount这三个生命周期函数的组合,那么我们也可以使用useEffect将其分离,首先对于componentDidMountcomponentWillUnmount,也就是想执行只运行一次的 effect(仅在组件挂载和卸载时执行),由于不存在任何依赖,那么对于第二个参数就是一个空的数组。如果省略了第二个参数的话,那么在组件的初始化和更新都会执行,一般情况下是并不希望这样的,因为Hooks的设计,每次setState都会重新执行组件函数,这样的话副作用函数就会频繁执行,所以通常来说还是尽量不要省略第二个参数。回到生命周期,通常如果在组件建立时建立了一个定时器,那么我们希望在组件销毁的时候将定时器销毁来避免内存泄露,那么在useEffect中返回一个函数调用去关闭定时器即可,在这里我们的关注点可以集中在一起而不用再分开两个生命周期去写了。

import { useEffect, useState } from "react";
import "./styles.css"; export default function App() {
const [count, setCount] = useState(0); useEffect(() => {
console.log("Component is mounted");
return () => console.log("Component is unmounted");
}, []); useEffect(() => {
console.log("Component is mounted or updated");
}) return (
<div>
<div>{count}</div>
<button onClick={() => setCount(count + 1)}>count + 1</button>
</div>
);
}

对于componentDidUpdate,之前如果是写class组件实现相同的功能的话,就需要在这个生命周期中嵌入很多的逻辑,使用useEffect就可以将各个关注点分离,分别处理其副作用,当然如果依然需要解除诸如订阅或者定时器等,依旧可以返回一个处理函数来处理。

import { useEffect, useState } from "react";
import "./styles.css"; export default function App() {
const [count, setCount] = useState(0); useEffect(() => {
console.log("Count is updated");
document.title = `count: ${count}`;
}, [count]); return (
<div>
<div>{count}</div>
<button onClick={() => setCount(count + 1)}>count + 1</button>
</div>
);
}

在文档中还指出请确保数组中包含了所有外部作用域中会随时间变化并且在effect中使用的变量,否则你的代码会引用到先前渲染中的旧变量。如果你传入了一个空数组[]effect内部的propsstate就会一直拥有其初始值。下面这个例子就会出现一个bug,在依赖数组中没有传递count,那么就会导致当effect执行时,创建的effect闭包会将count的值保存在该闭包当中,且初值为0,每隔一秒回调就会执行setCount(0 + 1),因此count永远不会超过1,此时如果我们将count加入到依赖数组中便可解决这个问题。对于这个问题,React提供了一个exhaustive-depsESLint规则作为eslint-plugin-react-hooks包的一部分,它会帮助你找出无法一致地处理更新的组件。

import { useEffect, useState } from "react";
import "./styles.css"; export default function App() {
const [count, setCount] = useState(0); useEffect(() => {
const id = setInterval(() => {
setCount(count + 1);
console.log(count + 1);
}, 1000);
return () => clearInterval(id);
}, []); // `count` 没有被指定为依赖 return (
<div>
<div>{count}</div>
<button onClick={() => setCount(count + 1)}>count + 1</button>
</div>
);
}

看起来和VueWatch很像,但是又不尽然相同,语法上的区别主要就在于useEffect可以监控多个属性的变化,Watch不行,当然Watch可以通过间接的方式实现,但是思想方面是不同的,Vue是监听值的变化而React是用以处理副作用。提到这个的主要原因是因为之前写Vue较多,就老想着通过Vue的角度来类比React的各项实现,感觉这样有好处也有弊端,好处就是很快能够上手,坏处就是很容易钻牛角尖,或者很容易陷入一个围城。有位大佬说的挺好的,你需要把Vue忘掉再来学习Hooks,虽然并不绝对但也很有道理。

当函数组件刷新渲染时,包含useEffect的组件整个运行过程如下:

  • 触发组件重新渲染,通过改变组件state或者组件的父组件重新渲染,导致子节点渲染。
  • 组件函数执行。
  • 组件渲染后呈现到屏幕上。
  • useEffect hook执行。

useLayoutEffect

useLayoutEffectuseEffect很像,函数签名也是一样,唯一的不同点就是useEffect是异步执行,而useLayoutEffect是同步执行的。当函数组件刷新渲染时,包含useLayoutEffect的组件整个运行过程如下:

  • 触发组件重新渲染,通过改变组件state或者组件的父组件重新渲染,导致子组件渲染。
  • 组件函数执行。
  • useLayoutEffect hook执行,React等待useLayoutEffect的函数执行完毕。
  • 组件渲染后呈现到屏幕上。

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://zhuanlan.zhihu.com/p/348701319
https://zhuanlan.zhihu.com/p/259766064
https://segmentfault.com/a/1190000039087645
http://www.ptbird.cn/react-hoot-useEffect.html
https://react.docschina.org/docs/hooks-effect.html
https://pengfeixc.com/blog/605af93600f1525af762a725
https://react.docschina.org/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies

useEffect与useLayoutEffect的更多相关文章

  1. React的useEffect与useLayoutEffect执行机制剖析

    引言 useEffect和useLayoutEffect是React官方推出的两个hooks,都是用来执行副作用的钩子函数,名字类似,功能相近,唯一不同的就是执行的时机有差异,今天这篇文章主要是从这两 ...

  2. useEffect 和 useLayoutEffect浅析

    执行时期的区别 useEffect 回调函数的执行时期 useEffect为异步执行,执行时期为 触发状态更新(如:setState,forceUpdate) React渲染函数执行(render) ...

  3. React中useLayoutEffect和useEffect的区别

    重点: 1.二者函数签名相同,调用方式是一致的 2. 怎么简单进行选择: 无脑选择useEffect,除非运行效果和你预期的不一致再试试useLayoutEffect 区别详解:useEffect是异 ...

  4. 精读《setState 做了什么》

    1 引言 setState 是 React 框架最常用的命令,它是用来更新状态的,这也是 React 框架划时代的功能. 但是 setState 函数是 react 包导出的,他们又是如何与 reac ...

  5. Preact(React)核心原理详解

    原创: 宝丁 玄说前端 本文作者:字节跳动 - 宝丁 一.Preact 是什么 二.Preact 和 React 的区别有哪些? 三.Preact 是怎么工作的 四.结合实际组件了解整体渲染流程 五. ...

  6. React Hooks用法大全

    前言 在 React 的世界中,有容器组件和 UI 组件之分,在 React Hooks 出现之前,UI 组件我们可以使用函数,无状态组件来展示 UI,而对于容器组件,函数组件就显得无能为力,我们依赖 ...

  7. React源码 commit阶段详解

    转: React源码 commit阶段详解 点击进入React源码调试仓库. 当render阶段完成后,意味着在内存中构建的workInProgress树所有更新工作已经完成,这包括树中fiber节点 ...

  8. PReact10.5.13源码理解之hook

    hook源码其实不多,但是实现的比较精巧:在diff/index.js中会有一些optison.diff这种钩子函数,hook中就用到了这些钩子函数.   在比如options._diff中将curr ...

  9. react之react Hooks

    函数组件,没有 class 组件中的 componentDidMount.componentDidUpdate 等生命周期方法,也没有 State,但这些可以通过 React Hook 实现. Rea ...

  10. ahooks 中那些控制“时机”的hook都是怎么实现的?

    本文是深入浅出 ahooks 源码系列文章的第五篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 本文来探索一下 ahooks 是怎么封装 React 的一些执行& ...

随机推荐

  1. 【js】 Object.prototype.toString.call()

    1,Object.prototype.toString这个方法的作用是什么  判断数据类型 2,为什么要用这个方法 是因为  js 中 一般的类型判断 对于 null,数组,对象 , 都会返回一样的结 ...

  2. css - 伪元素清除浮动

    .clearfix:after{ content:""; /*设置内容为空*/ height:0; /*高度为0*/ line-height:0; /*行高为0*/ display ...

  3. [转帖]TIDB-TIDB节点磁盘已满报警

    一.背景 今日突然收到tidb节点的磁盘报警,磁盘容量已经超过了80%,但是tidb是不放数据的,磁盘怎么会满,这里就需要排查了 二.问题排查 解决步骤 1.df -h查看哪里占用磁盘比较多,然后通过 ...

  4. [转帖]NVMe 与 AHCI

    https://www.cnblogs.com/zengkefu/p/5634345.html http://elf8848.iteye.com/blog/1731274 AHCI: NCQ技术,60 ...

  5. 【转帖】一文解析ethtool 命令的使用

    命令简介 ethtool命令用于查询和控制网络设备驱动程序和硬件设置,尤其是有线以太网设备,devname网卡的名称.网卡就像是交换机的一个端口,正常使用我们只是配置网卡IP地址等信息,网卡的速率.双 ...

  6. [转帖]Windows磁盘性能压测(2)-Fio

    http://www.manongjc.com/detail/59-qftscgqzitmxpaw.html 目录 一.腾讯云官网硬盘性能指标 二.使用fio测试硬盘性能指标 1. 测试工具相关 2. ...

  7. 使用smem 计算Oracle用户下内存占用情况.

    1. 本来计划使用 ps 命令进行查看, 但是发现ps 最多查询出来的是 RSS的内存数据, 会多添加很多冗余的内存数据量进来, 于是作罢 2. 找了下公司的方神, 说可以使用smem 然后简单看了下 ...

  8. Jumper Server 堡垒机搭建过程

    Jumper Server 堡垒机搭建过程 背景说明 公司组织考核, 要对一套系统进行安全设置.有一个项目是使用堡垒机进行登录 堡垒机有多种用途,可以实现日志审计和安全设置等. 买商业设备的话太困难了 ...

  9. [转载]关于NSA的EternalBlue(永恒之蓝) ms17-010漏洞利用

    2017年5月19日   感谢原作者:http://www.cnblogs.com/cnbluerain/           好久没有用这个日志了,最近WannaCry横行,媒体铺天盖地的报道,我这 ...

  10. JS ----- JS实用小功能

    1.复制页面上文字功能 function copyIdCode() { var idcode = document.getElementById("personIdcodeCopy" ...