web-dev-qa-db-ja.com

React.memo構文の問題の代わりにuseMemoを使用する

React Hooks useMemoを使用したデモを行う必要があります。次のような作業コードがあり、私がやりたいことをしています。

const SpeakerCardDetail = React.memo(
  ({id,...

このような構文を使用できることを示す link を見つけましたが、正確に理解できません。

これは私が得た限りです:

const SpeakerDetail = React.useMemo(() => {
   ({ id,

明らかにそうではありません。 React.memoが問題を解決することはわかっていますが、useMemoの動作を示す必要があり、使用できる代替構文があることを期待しています。

13
Pete

React.memoReact.useMemoはまったく同じではありません(名前の類似性に依存しないでください)。 React.memodoc からの引用は次のとおりです。

React.memo高次コンポーネント です。

そのため、同じプロパティで同じ出力をレンダリングする場合、コンポーネントのレンディションを最適化できるのはHOCです。

一方、React.useMemoはより一般的で、 メモされた値を返します

「作成」関数と依存関係の配列を渡します。 useMemoは、依存関係(aまたはb)のいずれかが変更された場合にのみ、メモされた値を再計算します。

const memoizedValue = useMemo(
  () => computeExpensiveValue(a, b), 
  [a, b]
);

また、ハッキングしてReact.memoの代わりに使用することもできますが、それはその目的ではなく、役立つ以上に混乱を招きます。 useMemoはフックであり、 特定の使用規則 に従います。

そして、この警告もあります:

将来的には、Reactは、以前にメモされた値を「忘れる」ことを選択し、オフスクリーンコンポーネントのメモリを解放するなど、次回のレンダリング時に再計算する可能性があります。コードがuseMemoなしでも機能するように記述してください—次に、それを追加してパフォーマンスを最適化します。

26
jayarjo

memoはHOCであり、useMemoはフックですが、それらを使用して同じ結果を得ることができます。

コンテキストに関しては、HOCはより古いReactパターンであり、クラスベースのコンポーネントと機能コンポーネントで同様に長年使用されています。現在も使用できます(廃止予定はありません)。

Hooksは比較的新しい概念(約1年)であり、機能コンポーネントを強化し、多くの場合、大幅に コードを簡略化 します。これが、多くの開発者がフックの使用に向かっている理由です。

とにかく、memouseMemoはどちらも関数と小道具の2つの引数を取ります。後続の再レンダリングで変更された小道具がない場合、関数は再度実行されず、代わりに前の結果を返します。実際、これはshouldComponentUpdateコールバックを純粋に機能的なアプローチに置き換えます。

memoを使用すると、コードは次のようになります。

const SpeakerCardDetail = React.memo(
  (props) => <div>{props.name}</div>
)

useMemoを使用すると、次のように記述できます。

const SpeakerCardDetail = (props) => useMemo(() => <div>{props.name}</div>)

useMemoはコンポーネント関数内で使用され、memoは関数をラップすることに注意してください。

より伝統的には、useMemoは次のように書くことができます:

function SpeakerCardDetail(props) {
  return useMemo(
    () => <div>{props.name}</div>
  )
}

ここで、上記のコードは毎回再レンダリングされ、useMemo関数は少し役に立たなくなります。その魔法を働かせるには、2番目の引数を追加する必要があります。 (memoは2番目の引数を指定しなくても機能しますが、追加してカスタマイズできます)

2番目の引数の形式にはわずかな違いがあります。 memoは、クラスコンポーネントに対してshouldComponentUpdateが行うように、以前の小道具と現在の小道具を比較する関数を想定しています。

const SpeakerCardDetail = React.memo(
  (props) => <div>{props.name}</div>
,
  // return true if passing nextProps to render would return the same result as passing prevProps to render, otherwise return false
  (prevProps, nextProps) => prevProps.name === nextProps.name
)

一方、useMemoでは、2番目の引数として配列が必要です。配列の値が変更されるたびに、関数は再度実行されます。

function SpeakerCardDetail(props) {
  return useMemo(
    () => <div>{props.name}</div>
  ,
    [props.name]
  )
}

それ以上の魔法はありません。 memouseMemoはどちらも関数の結果をメモするために使用されます。唯一の違いはmemoがHOCであることです(クラスと機能コンポーネントの両方をラップするために使用できます) useMemoはフックです(機能コンポーネント内でのみ使用できます)。

3
Petr Bela