在介紹這兩個hooks之前。讓我們先對比一下useEffect、useLayoutEffect、useInsertionEffect
-
執行時機:
useEffect
?在組件渲染完成后執行,屬于異步執行。useInsertionEffect
?在組件渲染并插入 DOM 后執行,也屬于異步執行。useLayoutEffect
?在組件渲染完成后立即同步執行,并在瀏覽器布局和繪制之前運行。
-
對 DOM 元素的訪問:
- 使用?
useEffect
?時,無法直接訪問具體的 DOM 元素。 - 使用?
useInsertionEffect
?時,可以通過傳遞 ref 引用來獲取對特定 DOM 元素的引用,并在回調函數中進行操作。 - 使用?
useLayoutEffect
?時,也可以通過 ref 獲取對 DOM 元素的引用,并在組件渲染完成后立即同步執行副作用操作。
- 使用?
-
影響瀏覽器渲染的時機:
useEffect
?和?useInsertionEffect
?的執行時機都是在瀏覽器渲染之后,不會阻塞頁面的渲染過程。useLayoutEffect
?的執行是同步的,并且在瀏覽器布局和繪制之前運行,因此如果其中的副作用操作比較耗時,可能會阻塞瀏覽器的渲染過程,導致用戶界面的卡頓
一、useLayoutEffect
1、作用:
它在組件完成渲染后同步執行副作用操作,并在瀏覽器布局和繪制之前運行。它與 useEffect
的使用方式類似,但在執行時機上有所不同。
具體來說,useLayoutEffect
的執行時機如下:
- 在組件渲染完成后立即執行。
- 在瀏覽器執行布局和繪制之前運行,以確保在瀏覽器更新屏幕之前執行副作用操作。
這意味著 useLayoutEffect
會在 DOM 更新之后、瀏覽器繪制之前同步執行,使得其副作用操作能夠立即對 DOM 進行更改,而這些更改可能會影響到瀏覽器的布局和繪制。
2、注意事項
由于 useLayoutEffect
的執行是同步的,如果其中的副作用操作比較耗時,會阻塞瀏覽器的渲染過程,導致用戶界面的卡頓。因此,在使用 useLayoutEffect
時,應該謹慎處理副作用操作的性能問題。
3、用法:同useEffect類似,一個回調函數,一個依賴項。
4、示例
import { useLayoutEffect, useRef } from 'react';function Example() {const ref = useRef(null);const [count, setCount] = useState(0);useLayoutEffect(() => {console.log('useLayoutEffect - Component rendered:', ref.current);ref.current.style.backgroundColor = 'red';return () => {console.log('useLayoutEffect cleanup');};}, [count]);return (<div><div ref={ref}>Hello World</div><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}
在這個例子中,我們創建了一個 ref
引用,用于訪問 DOM 元素。在 useLayoutEffect
的回調函數中,我們可以通過 ref.current
獲取到對應的 <div>
元素,并設置其背景顏色為紅色。此外,我們還在 deps
參數中傳遞了 count
狀態,表示只有當 count
發生變化時才執行副作用操作。
二、useInsertionEffect
1、作用
它用于在組件渲染并插入 DOM 后執行副作用操作。與 useEffect
和 useLayoutEffect
不同,useInsertionEffect
的回調函數會在瀏覽器完成對 DOM 元素的插入操作后才運行。
2、用法
和useEffect類似,不具體說明
3、注意事項:
由于 useInsertionEffect
的回調函數是在瀏覽器完成對 DOM 元素的插入操作后才運行,因此可以在其中直接訪問具體的 DOM 元素。這與 useEffect
和 useLayoutEffect
不同,它們無法直接訪問具體的 DOM 元素。因此,在處理需要訪問具體 DOM 元素的副作用操作時,可以優先考慮使用 useInsertionEffect
。
4、示例:
import { useInsertionEffect, useRef } from 'react';function Example() {const ref = useRef(null);const [count, setCount] = useState(0);useInsertionEffect(() => {console.log('useInsertionEffect - Component inserted:', ref.current);ref.current.style.backgroundColor = 'red';return () => {console.log('useInsertionEffect cleanup');};}, [count]);return (<div><button onClick={() => setCount(count + 1)}>Click me</button><div ref={ref}>Hello World</div></div>);
}
在這個例子中,我們創建了一個 ref
引用,用于訪問 DOM 元素。在 useInsertionEffect
的回調函數中,我們可以通過 ref.current
獲取到對應的 <div>
元素,并設置其背景顏色為紅色。此外,我們還在 deps
參數中傳遞了 count
狀態,表示只有當 count
發生變化時才執行副作用操作。