useEffect与useLayoutEffect
useEffect与useLayoutEffect
useEffect
与useLayoutEffect
可以统称为Effect Hook
,Effect Hook
可以在函数组件中执行副作用操作,副作用是指函数或者表达式的行为依赖于外部环境,或者在这里可以理解为修改了某状态会对其他的状态造成影响,这个影响就是副作用,数据获取,设置订阅以及手动更改React
组件中的DOM
都属于副作用。
useEffect
useEffect Hook
可以看做 componentDidMount
、componentDidUpdate
和componentWillUnmount
这三个生命周期函数的组合,但是使用多个Effect
实现关注点分离,也就是说useEffect
的粒度更低,可以将各个关注的位置分离处理副作用。
既然是对componentDidMount
、componentDidUpdate
和componentWillUnmount
这三个生命周期函数的组合,那么我们也可以使用useEffect
将其分离,首先对于componentDidMount
与componentWillUnmount
,也就是想执行只运行一次的 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
内部的props
和state
就会一直拥有其初始值。下面这个例子就会出现一个bug
,在依赖数组中没有传递count
,那么就会导致当effect
执行时,创建的effect
闭包会将count
的值保存在该闭包当中,且初值为0
,每隔一秒回调就会执行setCount(0 + 1)
,因此count
永远不会超过1
,此时如果我们将count
加入到依赖数组中便可解决这个问题。对于这个问题,React
提供了一个exhaustive-deps
的ESLint
规则作为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>);
}
看起来和Vue
的Watch
很像,但是又不尽然相同,语法上的区别主要就在于useEffect
可以监控多个属性的变化,Watch
不行,当然Watch
可以通过间接的方式实现,但是思想方面是不同的,Vue
是监听值的变化而React
是用以处理副作用。提到这个的主要原因是因为之前写Vue
较多,就老想着通过Vue
的角度来类比React
的各项实现,感觉这样有好处也有弊端,好处就是很快能够上手,坏处就是很容易钻牛角尖,或者很容易陷入一个围城。有位大佬说的挺好的,你需要把Vue
忘掉再来学习Hooks
,虽然并不绝对但也很有道理。
当函数组件刷新渲染时,包含useEffect
的组件整个运行过程如下:
- 触发组件重新渲染,通过改变组件
state
或者组件的父组件重新渲染,导致子节点渲染。 - 组件函数执行。
- 组件渲染后呈现到屏幕上。
useEffect hook
执行。
useLayoutEffect
useLayoutEffect
和useEffect
很像,函数签名也是一样,唯一的不同点就是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相关推荐
- 如何使 React 中的 useEffect、useLayoutEffect 只调用一次
如何使 React 中的 useEffect.useLayoutEffect 只调用一次 Hook 是 React 16.8 的新增特性,旨在替代原来 React 中的 Class 组件.Reac ...
- [react] useEffect和useLayoutEffect有什么区别?
[react] useEffect和useLayoutEffect有什么区别? useEffect是异步的,所谓的异步就是利用requestIdleCallback,在浏览器空闲时间执行传入的call ...
- useEffect和useLayoutEffect的区别
react hook面世已经有一段时间了,相信很多人都已经在代码中用上了hooks.而对于 useEffect 和 useLayoutEffect,我们使用的最多的应该就是useEffect.那他们两 ...
- useEffect和useLayoutEffect区别
如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWil ...
- 面试官:useLayoutEffect和useEffect的区别
面试官:useLayoutEffect和useEffect的区别 hello,这里是潇晨,大家面试的过程中有没有遇到过这样的问题呢,useLayoutEffect和useEffect的区别是什么,大家 ...
- React Hooks的使用(三)——useRef、useImperativeHandle、useLayoutEffect解析、自定义Hook
一.useRef useRef返回一个ref对象,返回的ref对象再组件的整个生命周期保持不变. 最常用的ref是两种用法: 用法一:引入DOM(或者组件,但是需要是class组件)元素: 案例一:引 ...
- React学习笔记6:React Hooks API总结
useState-保存状态(惰性初始化) 作用 函数组件添加状态 注意事项 初始化以及更新state 用来声明状态变量 使用步骤(使用useState来创建状态) 引入import React,{us ...
- hook修改信息_React系列二十一 Hook(二)高级使用
一. Hook高级使用 1.1. useReducer 很多人看到useReducer的第一反应应该是redux的某个替代品,其实并不是. useReducer仅仅是useState的一种替代方案: ...
- sqlbulkcopy是覆盖式更新吗_React 328道最全面试题(持续更新)
今天的React题没有太多的故事-- 半个月前出了248个Vue的知识点,受到很多朋友的关注,都强烈要求再出多些React相前的面试题,受到大家的邀请,我又找了20多个React的使用者,他们给出了3 ...
最新文章
- C# 写Windows服务
- 通用权限管理模块系列——需求分析——列举需求
- python模块-paramiko-修改源码(demo实例)
- Android获取的状态栏高度,Android中获取状态栏高度的两种方法分享
- python 参数个数 同名函数_如何在python中编写不同参数的同名方法
- paip.提升用户体验----c++ 源码字体自定义制造总结
- Alex 的 Hadoop 菜鸟教程: 第3课 Hadoop 安装教程 - 非HA方式 (一台服务器)
- @Tableau 设计技巧 8.2:tableau官方教程(中文版pdf)
- Python-计量经济学案例
- iOS Gif分解与展示
- 自动切换输入法 for Mac(输入法辅助工具)
- Java计算机毕业设计图书馆座位预约管理系统源码+系统+数据库+lw文档
- 让女人无法抗拒的30句表白【实用】
- Android百度定位获取经纬度
- LZY的计算器(暴力)
- LeetCode1419. 数青蛙
- Mysql错误代码1045
- 如何查看一个Visual Studio项目是用哪个VS版本开发的
- 有了方差为什么需要标准差?
- win10更新后office2016图标显示空白