useCallback 鉤子會記住函數本身,而不是它的回傳值。 useCallback 快取函數引用
元件內部宣告的函數會在每次渲染時重新創建,類似於變數。不同之處在於,它每次都會使用不同的參考進行渲染。所以,
依賴此函數的 useEffect 將在每次渲染時再次執行:
import React, { useState, useEffect, useCallback } from 'react'; // Parent Component const ParentComponent = () => { const [count, setCount] = useState(0); const [text, setText] = useState(""); // Function declared inside the component const handleClick = () => { setCount(count + 1); }; // useEffect depending on handleClick useEffect(() => { console.log("handleClick changed, running useEffect"); }, [handleClick]); return ( <div> <button onClick={handleClick}>Increment Count</button> <p>Count: {count}</p> <ChildComponent handleClick={handleClick} /> </div> ); }; // Child Component const ChildComponent = React.memo(({ handleClick }) => { console.log("ChildComponent re-rendered"); return <button onClick={handleClick}>Child Increment</button>; }); export default ParentComponent;
子組件也會發生類似的情況:
當我們將一個具有昂貴或「慢」渲染邏輯的元件作為另一個元件的子元件時,每次父元件渲染時,其所有子元件也會重新渲染。
為了防止這些不必要的重新渲染,我們可以使用 React.memo。這個高階元件會快取子元件,確保它僅在其 props 實際變更時才重新渲染。然而,當函數作為 props 傳遞時,有一個微妙的問題,這會導致子程序重新渲染,即使它不應該重新渲染。
函數所引用的問題
想像一下我們有一個 SlowComponent 作為 App 的子元件。在 App 中,我們有一個狀態會在按鈕點擊時發生變化,從而觸發 App 的重新渲染。儘管我們沒有更改 SlowComponent 的 props,但它仍然會在每次點擊時重新渲染。
為什麼?在每次渲染時,handleClick 函數都會使用新的參考重新創建,React 將其解釋為更改後的 prop,導致 SlowComponent 重新渲染。為了解決這個問題,我們使用 useCallback 鉤子來跨渲染快取函數的參考。
使用 useCallback 的解決方案
透過將handleClick包裝在useCallback中,我們告訴React僅在特定依賴項發生變化時重新建立它。文法如下:
const cachedFn = useCallback(fn, [dependencies]);
在我們的範例中應用 useCallback
讓我們看看如何使用 useCallback 來最佳化我們的 App 元件:
import React, { useState, useCallback } from "react"; const App = () => { const [count, setCount] = useState(0); const [value, setValue] = useState(""); // Wrapping handleClick with useCallback to cache its reference const handleClick = useCallback(() => { setValue("Kunal"); }, [setValue]); return ( <div> <button onClick={() => setCount(count + 1)}>Increment Count</button> <p>Count: {count}</p> <SlowComponent handleClick={handleClick} /> </div> ); }; const SlowComponent = React.memo(({ handleClick }) => { // Intentially making the component slow for (let i = 0; i < 1000000000; i++) {} console.log("SlowComponent re-rendered"); return <button onClick={handleClick}>Click me in SlowComponent</button>; }); export default App;
何時使用 useCallback
以上是理解 Reactjs 中的 useCallback的詳細內容。更多資訊請關注PHP中文網其他相關文章!