一、对于useLayoutEffect
的形容
Reactjs文档里这样形容useLayoutEffect
:
The signature is identical to
useEffect
, but it fires synchronously after all DOM mutationsonly differs in when it is fired
即useLayoutEffect
跟useEffect
函数签名统一,然而在DOM批改后同步触发,这是和useEffect
惟一的区别。
二、何时应用useLayoutEffect
?
假如有个展现随机数字的case,当count
为0时随机生成个数字:
2.1 先应用useEffect
实现:
import { useState, useEffect, useLayoutEffect } from 'react'export default function App() { const [count, setCount] = useState(0); useEffect(() => { console.log(`useEffect - count=${count}`) // 耗时的操作 const pre = Date.now(); while(Date.now() - pre < 500) {} // count为0时从新生成个随机数 if (count === 0) { setCount(10 + Math.random() * 200); } }, [count]); // 点击DIV重置count return ( <div onClick={() => setCount(0)}>{count}</div> );}
能够看到展现0的过程。
2.2 改用useLayoutEffect
实现:
import { useState, useEffect, useLayoutEffect } from 'react'export default function App() { const [count, setCount] = useState(0); useLayoutEffect(() => { console.log(`useLayoutEffect - count=${count}`) // 耗时的操作 const pre = Date.now(); while(Date.now() - pre < 500) {} if (count === 0) { setCount(10 + Math.random() * 200); } }, [count]); return ( <div onClick={() => setCount(0)}>{count}</div> );}
没有闪动,当点击 div,count 更新为 0,此时页面并不会渲染,而是期待
useLayoutEffect
外部状态批改后,才会去更新页面,所以页面不会闪动。Updates scheduled inside
useLayoutEffect
will be flushed synchronously, before the browser has a chance to paint- 然而也能够发现页面更新的比拟卡顿,因为
useLayoutEffect
会阻塞浏览器渲染,正好本例中useLayoutEffect
的实参函数里有个耗时操作,所以页面更新比拟卡顿。
2.3 useLayoutEffect
和componentDidMount
、componentDidUpdate
触发机会统一
下面的例子改用class
组件实现试试:
import React from 'react'export default class App extends React.Component { constructor(props) { super(props); this.state = { count: 0 } } componentDidUpdate() { // 耗时的操作 const pre = Date.now(); while(Date.now() - pre < 500) {} } increaseCount = () => { this.setState(({ count }) => { return { count: count + 1} }) } render() { const { count } = this.state; return ( <div onClick={this.increaseCount}>{count}</div> ) }}
跟useLayoutEffect
成果一样:也是看不到闪动,但也比拟卡顿。
2.4 综上:
useLayoutEffect
和componentDidMount
和componentDidUpdate
触发机会统一(都在在DOM批改后且浏览器渲染之前);useLayoutEffect
要比useEffect
更早的触发执行;useLayoutEffect
会阻塞浏览器渲染,切记执行同步的耗时操作。
三、小结:
除非要批改DOM并且不让用户看到批改DOM的过程,才思考应用useLayoutEffect
,否则该当应用useEffect
。
留神:如果只是为了获取DOM属性(或其它get操作),则没必要应用useLayoutEffect
,该当应用useEffect
。
四、参考:
整顿自gitHub笔记useEffect
和useLayoutEffect
到底有什么区别?