React 中useLayoutEffect 和 useEffect 區(qū)別和使用場景
useEffect 和 useLayoutEffect 都是 React 的副作用 Hook,但它們最大的區(qū)別是:
執(zhí)行時機不同。
一句話理解
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ū)別(面試重點)
| 對比 | useEffect | useLayoutEffect |
|---|---|---|
| 執(zhí)行時機 | 瀏覽器繪制后 | 瀏覽器繪制前 |
| 是否阻塞渲染 | 不阻塞 | 阻塞 |
| 執(zhí)行方式 | 異步 | 同步 |
| 是否可能造成卡頓 | 不容易 | 容易 |
| 推薦程度 | 默認優(yōu)先使用 | 特殊場景再用 |
使用場景
一、useEffect(99%場景)
這是最常用的。
適合:
- 請求接口
- 訂閱事件
- 定時器
- localStorage
- 數(shù)據(jù)獲取
- websocket
- 日志埋點
示例:
useEffect(() => {
fetchUser()
}, [])或者:
useEffect(() => {
const timer = setInterval(() => {
console.log('timer')
}, 1000)
return () => clearInterval(timer)
}, [])二、useLayoutEffect(操作 DOM)
只有當你:
“必須在頁面繪制前修改 DOM”
才用它。
典型場景:
1. 獲取 DOM 尺寸
因為此時 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'
}, [])因為:
測量DOM
+
修改DOM
必須同步完成。
為什么不要亂用 useLayoutEffect
因為它會:阻塞瀏覽器繪制
如果里面:
- 請求接口
- 大計算
- 循環(huán)
- await
都會導致:
白屏
卡頓
掉幀
所以 React 官方建議:
優(yōu)先使用 useEffect。
只有“必須同步操作 DOM”才使用 useLayoutEffect。
一個經(jīng)典面試題
useLayoutEffect 會不會阻塞頁面渲染?
會。
因為:它在瀏覽器 paint 前同步執(zhí)行
所以會阻塞繪制。
useEffect 會不會?
不會。
因為:頁面已經(jīng)繪制完了
它是異步調(diào)度。
React18 注意點
在 React18 嚴格模式下:<React.StrictMode>
開發(fā)環(huán)境會:執(zhí)行兩次 effect
包括:
- useEffect
- useLayoutEffect
這是為了檢查副作用是否安全。
生產(chǎn)環(huán)境不會。
服務端渲染 SSR 注意
useLayoutEffect 在 SSR 中會警告:
useLayoutEffect does nothing on the server
因為:服務端沒有 DOM
很多庫會寫:
const useIsomorphicLayoutEffect =
typeof window !== 'undefined'
? useLayoutEffect
: useEffect避免 SSR 報警告。
最佳實踐(非常重要)
默認:useEffect
只有:需要同步操作DOM
才使用:useLayoutEffect
面試總結版(背誦)
useEffect 和 useLayoutEffect 都用于處理副作用。
區(qū)別是:
- useEffect 在頁面繪制后異步執(zhí)行,不阻塞渲染,適合請求接口、訂閱事件等普通副作用。
- useLayoutEffect 在 DOM 更新后、瀏覽器繪制前同步執(zhí)行,會阻塞頁面渲染,適合 DOM 測量、同步修改 DOM、防止閃爍等場景。
開發(fā)中應優(yōu)先使用 useEffect,只有需要同步操作 DOM 時才使用 useLayoutEffect。
到此這篇關于React 中useLayoutEffect 和 useEffect 區(qū)別和使用場景的文章就介紹到這了,更多相關React useLayoutEffect 和 useEffect 區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解前端路由實現(xiàn)與react-router使用姿勢
本篇文章主要介紹了詳解前端路由和react-router使用姿勢,詳細的介紹了react-router的用法,有興趣的可以了解一下2017-08-08
React Router V5:使用HOC組件實現(xiàn)路由攔截功能
這篇文章主要介紹了React Router V5:使用HOC組件實現(xiàn)路由攔截功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03

