React 中useLayoutEffect 和 useEffect 區(qū)別和使用場景
useEffect 和 useLayoutEffect 都是 React 的副作用 Hook,但它們最大的區(qū)別是:
執(zhí)行時(shí)機(jī)不同。
一句話理解
useEffect
?? 頁面渲染完成后異步執(zhí)行(不阻塞頁面繪制)useLayoutEffect
?? DOM 更新后、瀏覽器繪制前同步執(zhí)行(會阻塞頁面繪制)
React 渲染流程理解
React 更新頁面大致流程:
1. React render
2. 更新 DOM
3. useLayoutEffect 執(zhí)行
4. 瀏覽器繪制頁面(paint)
5. useEffect 執(zhí)行
所以:
useLayoutEffect 更早
useEffect 更晚
圖解理解
useEffect
useEffect(() => {
console.log('effect')
}, [])流程:
DOM更新
↓
頁面先顯示
↓
effect執(zhí)行
用戶會先看到頁面。
useLayoutEffect
useLayoutEffect(() => {
console.log('layout effect')
}, [])流程:
DOM更新
↓
layout effect執(zhí)行
↓
頁面顯示
effect 執(zhí)行完頁面才顯示。
核心區(qū)別(面試重點(diǎn))
| 對比 | useEffect | useLayoutEffect |
|---|---|---|
| 執(zhí)行時(shí)機(jī) | 瀏覽器繪制后 | 瀏覽器繪制前 |
| 是否阻塞渲染 | 不阻塞 | 阻塞 |
| 執(zhí)行方式 | 異步 | 同步 |
| 是否可能造成卡頓 | 不容易 | 容易 |
| 推薦程度 | 默認(rèn)優(yōu)先使用 | 特殊場景再用 |
使用場景
一、useEffect(99%場景)
這是最常用的。
適合:
- 請求接口
- 訂閱事件
- 定時(shí)器
- localStorage
- 數(shù)據(jù)獲取
- websocket
- 日志埋點(diǎn)
示例:
useEffect(() => {
fetchUser()
}, [])或者:
useEffect(() => {
const timer = setInterval(() => {
console.log('timer')
}, 1000)
return () => clearInterval(timer)
}, [])二、useLayoutEffect(操作 DOM)
只有當(dāng)你:
“必須在頁面繪制前修改 DOM”
才用它。
典型場景:
1. 獲取 DOM 尺寸
因?yàn)榇藭r(shí) DOM 已更新。
useLayoutEffect(() => {
const width = divRef.current.offsetWidth
console.log(width)
}, [])2. 防止頁面閃爍(非常經(jīng)典)
例如:
useEffect(() => {
div.style.left = '100px'
}, [])會發(fā)生:
先顯示原位置
再瞬移
用戶能看到閃動。
而:
useLayoutEffect(() => {
div.style.left = '100px'
}, [])瀏覽器繪制前就改好了。
用戶看不到閃動。
3. 動畫初始化
例如:
- GSAP
- Framer Motion
- 拖拽庫
- 虛擬列表
很多庫內(nèi)部都用 useLayoutEffect。
4. 同步測量 + 修改 DOM
經(jīng)典:
useLayoutEffect(() => {
const height = ref.current.offsetHeight
ref.current.style.height = height + 100 + 'px'
}, [])因?yàn)椋?/p>
測量DOM
+
修改DOM
必須同步完成。
為什么不要亂用 useLayoutEffect
因?yàn)樗鼤?code>阻塞瀏覽器繪制
如果里面:
- 請求接口
- 大計(jì)算
- 循環(huán)
- await
都會導(dǎo)致:
白屏
卡頓
掉幀
所以 React 官方建議:
優(yōu)先使用 useEffect。
只有“必須同步操作 DOM”才使用 useLayoutEffect。
一個(gè)經(jīng)典面試題
useLayoutEffect 會不會阻塞頁面渲染?
會。
因?yàn)椋?code>它在瀏覽器 paint 前同步執(zhí)行
所以會阻塞繪制。
useEffect 會不會?
不會。
因?yàn)椋?code>頁面已經(jīng)繪制完了
它是異步調(diào)度。
React18 注意點(diǎn)
在 React18 嚴(yán)格模式下:<React.StrictMode>
開發(fā)環(huán)境會:執(zhí)行兩次 effect
包括:
- useEffect
- useLayoutEffect
這是為了檢查副作用是否安全。
生產(chǎn)環(huán)境不會。
服務(wù)端渲染 SSR 注意
useLayoutEffect 在 SSR 中會警告:
useLayoutEffect does nothing on the server
因?yàn)椋?code>服務(wù)端沒有 DOM
很多庫會寫:
const useIsomorphicLayoutEffect =
typeof window !== 'undefined'
? useLayoutEffect
: useEffect避免 SSR 報(bào)警告。
最佳實(shí)踐(非常重要)
默認(rèn):useEffect
只有:需要同步操作DOM
才使用:useLayoutEffect
面試總結(jié)版(背誦)
useEffect 和 useLayoutEffect 都用于處理副作用。
區(qū)別是:
- useEffect 在頁面繪制后異步執(zhí)行,不阻塞渲染,適合請求接口、訂閱事件等普通副作用。
- useLayoutEffect 在 DOM 更新后、瀏覽器繪制前同步執(zhí)行,會阻塞頁面渲染,適合 DOM 測量、同步修改 DOM、防止閃爍等場景。
開發(fā)中應(yīng)優(yōu)先使用 useEffect,只有需要同步操作 DOM 時(shí)才使用 useLayoutEffect。
到此這篇關(guān)于React 中useLayoutEffect 和 useEffect 區(qū)別和使用場景的文章就介紹到這了,更多相關(guān)React useLayoutEffect 和 useEffect 區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解前端路由實(shí)現(xiàn)與react-router使用姿勢
本篇文章主要介紹了詳解前端路由和react-router使用姿勢,詳細(xì)的介紹了react-router的用法,有興趣的可以了解一下2017-08-08
React報(bào)錯(cuò)之組件不能作為JSX組件使用的解決方法
本文主要介紹了React報(bào)錯(cuò)之組件不能作為JSX組件使用的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
React實(shí)現(xiàn)點(diǎn)擊刪除列表中對應(yīng)項(xiàng)
本文主要介紹了React 點(diǎn)擊刪除列表中對應(yīng)項(xiàng)的方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01
React Router V5:使用HOC組件實(shí)現(xiàn)路由攔截功能
這篇文章主要介紹了React Router V5:使用HOC組件實(shí)現(xiàn)路由攔截功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
react antd表格中渲染一張或多張圖片的實(shí)例
這篇文章主要介紹了react antd表格中渲染一張或多張圖片的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
react寫一個(gè)select組件的實(shí)現(xiàn)代碼
這篇文章主要介紹了react寫一個(gè)select組件的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
react PropTypes校驗(yàn)傳遞的值操作示例
這篇文章主要介紹了react PropTypes校驗(yàn)傳遞的值操作,結(jié)合實(shí)例形式分析了react PropTypes針對傳遞的值進(jìn)行校驗(yàn)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-04-04

