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 只调用一次

    如何使 React 中的 useEffect.useLayoutEffect 只调用一次   Hook 是 React 16.8 的新增特性,旨在替代原来 React 中的 Class 组件.Reac ...

  2. [react] useEffect和useLayoutEffect有什么区别?

    [react] useEffect和useLayoutEffect有什么区别? useEffect是异步的,所谓的异步就是利用requestIdleCallback,在浏览器空闲时间执行传入的call ...

  3. useEffect和useLayoutEffect的区别

    react hook面世已经有一段时间了,相信很多人都已经在代码中用上了hooks.而对于 useEffect 和 useLayoutEffect,我们使用的最多的应该就是useEffect.那他们两 ...

  4. useEffect和useLayoutEffect区别

    如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWil ...

  5. 面试官:useLayoutEffect和useEffect的区别

    面试官:useLayoutEffect和useEffect的区别 hello,这里是潇晨,大家面试的过程中有没有遇到过这样的问题呢,useLayoutEffect和useEffect的区别是什么,大家 ...

  6. React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook

    一.useRef useRef返回一个ref对象,返回的ref对象再组件的整个生命周期保持不变. 最常用的ref是两种用法: 用法一:引入DOM(或者组件,但是需要是class组件)元素: 案例一:引 ...

  7. React学习笔记6:React Hooks API总结

    useState-保存状态(惰性初始化) 作用 函数组件添加状态 注意事项 初始化以及更新state 用来声明状态变量 使用步骤(使用useState来创建状态) 引入import React,{us ...

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

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

  9. sqlbulkcopy是覆盖式更新吗_React 328道最全面试题(持续更新)

    今天的React题没有太多的故事-- 半个月前出了248个Vue的知识点,受到很多朋友的关注,都强烈要求再出多些React相前的面试题,受到大家的邀请,我又找了20多个React的使用者,他们给出了3 ...

最新文章

  1. C# 写Windows服务
  2. 通用权限管理模块系列——需求分析——列举需求
  3. python模块-paramiko-修改源码(demo实例)
  4. Android获取的状态栏高度,Android中获取状态栏高度的两种方法分享
  5. python 参数个数 同名函数_如何在python中编写不同参数的同名方法
  6. paip.提升用户体验----c++ 源码字体自定义制造总结
  7. Alex 的 Hadoop 菜鸟教程: 第3课 Hadoop 安装教程 - 非HA方式 (一台服务器)
  8. @Tableau 设计技巧 8.2:tableau官方教程(中文版pdf)
  9. Python-计量经济学案例
  10. iOS Gif分解与展示
  11. 自动切换输入法 for Mac(输入法辅助工具)
  12. Java计算机毕业设计图书馆座位预约管理系统源码+系统+数据库+lw文档
  13. 让女人无法抗拒的30句表白【实用】
  14. Android百度定位获取经纬度
  15. LZY的计算器(暴力)
  16. LeetCode1419. 数青蛙
  17. Mysql错误代码1045
  18. 如何查看一个Visual Studio项目是用哪个VS版本开发的
  19. 有了方差为什么需要标准差?
  20. win10更新后office2016图标显示空白

热门文章

  1. 如何更好地理解Javascript对象的自有属性和原型继承属性
  2. Cookie、Session、Token、JWT区别与联系
  3. Linux练习(函数调用复制文件)
  4. java并发临界资源管理
  5. 用sed和awk实现将文本中的上下两行合并为一行(转载)
  6. AngularJS 指令实践指南(二)
  7. 基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现
  8. php+mysql+apache 环境搭建
  9. Django 源码阅读
  10. C#学习笔记之-----倒序输出字符串