首頁 > web前端 > js教程 > 理解 Reactjs 中的 useCallback

理解 Reactjs 中的 useCallback

Linda Hamilton
發布: 2024-10-27 01:51:03
原創
979 人瀏覽過

Understanding useCallback in Reactjs
useCallback 鉤子會記住函數本身,而不是它的回傳值。 useCallback 快取函數引用

元件內部宣告的函數會在每次渲染時重新創建,類似於變數。不同之處在於,它每次都會使用不同的參考進行渲染。所以,

  • 依賴此函數的 useEffect 將在每次渲染時再次執行。
  • 子組件也會發生類似的情況。

依賴此函數的 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]);
登入後複製
  • fn:這是您要快取的函數定義。它可以接受參數並傳回任何值。
  • 依賴項:這是一個依賴項數組。如果任何依賴項發生變化,React 將重新建立 fn。 在第一次渲染時,React 會建立並快取該函數。在後續渲染中,只要依賴項沒有改變,就會傳回快取的函數,確保它有一個穩定的參考。

在我們的範例中應用 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

  • 當您為元件內的元素定義了事件處理程序時,請將它們包裝在 useCallback 中,以避免不必要地重新建立事件處理程序。
  • 當您在 useEffect 中呼叫函數時,通常會將該函數作為依賴項傳遞。為了避免在每次渲染時不必要地使用 useEffect,請將函數定義包裝在 useCallback 中。
  • 如果您正在編寫自訂鉤子,並且它會傳回一個函數,建議將其包裝在 useCallback 中。因此,用戶無需擔心優化鉤子 - 相反,他們可以專注於自己的程式碼。

Understanding useCallback in Reactjs

以上是理解 Reactjs 中的 useCallback的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板