布局上
- useEffect在浏览器渲染完成后执行
- useLayoutEffect在DOM更新后执行
特点
useLayoutEffect
总是比useEffect
先执行;useLayoutEffect与componentDidMount、componentDidUpdate调用时机相同,都是在DOM更新后,页面渲染前调用;useEffect在页面渲染后调用- 使用
useLayoutEffect
时,里面的作用最好改变布局 ,否则会占用等待时间,useLayoutEffect中进行DOM操作,这些DOM修改会与react做出的修改一起被一次性的渲染到页面上,只会产生一次回流、重绘,防止页面抖动
经验
- 为了用户体验,优先使用
useEffect
(优先渲染),因为大部分时候,我们不会去改变DOM useLayoutEffect
会影响用户看到画面变化的时间
例子
- useEffect
import React, { useEffect, useState, useLayoutEffect, useRef } from 'react'; import { render } from 'react-dom'; function App() { const [count, setCount] = useState(0); useEffect(() => { if (count === 0) { const randomNum = 10 + Math.random()*200 setCount(10 + Math.random()*200); } }, [count]); return ( <div onClick={() => setCount(0)}>{count}</div> ); } render(<App />, document.getElementById('root'));
在线进行试验:React (forked) - StackBlitz
-
useLayoutEffect
import React, { useEffect, useState, useLayoutEffect, useRef } from 'react'; import { render } from 'react-dom'; function App() { const [count, setCount] = useState(0); useLayoutEffect(() => { if (count === 0) { const randomNum = 10 + Math.random()*200 setCount(10 + Math.random()*200); } }, [count]); return ( <div onClick={() => setCount(0)}>{count}</div> ); } render(<App />, document.getElementById('root'));