Reactjs の useCallback を理解する

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-27 01:51:03981ブラウズ

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 を使用できます。この上位コンポーネントは子コンポーネントをキャッシュし、プロパティが実際に変更された場合にのみ再レンダリングされるようにします。ただし、関数を小道具として渡す場合には微妙な問題があり、それにより、子が再レンダリングされるべきではない場合でも再レンダリングされてしまいます。

関数参照の問題

App の子として SlowComponent があると想像してください。アプリには、ボタンのクリック時に状態が変化し、アプリの再レンダリングがトリガーされます。 SlowComponent のプロパティは変更していませんが、クリックするたびに再レンダリングされます。

なぜですか?レンダリングのたびに、handleClick 関数が新しい参照で再作成され、React は変更されたプロップとして解釈し、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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。