開発者ドキュメント

ReactuseMemoフックを理解する

序章

React 16.8のリリースにより、Reactアプリケーションで使用できる便利なフックがたくさんあります。 16.8で導入された組み込みフックの1つは、useMemoです。 このフックは、アプリケーションのパフォーマンスを向上させる可能性があります。

この記事では、Reactで再レンダリングがどのように機能するか、それがReactアプリケーションにとって重要な考慮事項である理由、およびuseMemoフックがそれを活用してアプリケーションのパフォーマンスを向上させる方法について説明します。 また、useMemoがパフォーマンスの問題を引き起こす可能性がある場合についても学習します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

参照の平等と高価な操作

useMemoが対処しようとしている2つの問題があります。

コンポーネントのライフサイクルでは、更新が行われると、Reactはコンポーネントを再レンダリングします。 Reactがコンポーネントの変更をチェックするとき、JavaScriptが同等性と浅い比較を処理する方法が原因で、意図しないまたは予期しない変更を検出する場合があります。 Reactアプリケーションでのこの変更により、不必要に再レンダリングされます。

さらに、その再レンダリングが長いfor loopのようにコストのかかる操作である場合、パフォーマンスが低下する可能性があります。 高価な操作は、時間、メモリ、または処理のいずれかでコストがかかる可能性があります。 潜在的な技術的な問題に加えて、これはユーザーエクスペリエンスの低下につながる可能性があります。

一部が再レンダリングされると、コンポーネントツリー全体が再レンダリングされます。

したがって、Reactはこれを修正するためのmemoのアイデアをリリースしました。

メモ化を理解する

メモ化は、メモ化する複雑な関数を渡す最適化手法です。 メモ化では、同じパラメーターが後で渡されたときに結果が「記憶」されます。

関数compute1 + 1がある場合、2を返します。 ただし、メモ化を使用している場合は、次に1を関数で実行しても、それらは加算されません。 追加機能を実行せずに、答えが2であることを覚えているだけです。

公式のReactドキュメントから、useMemoの署名は次のようになります。

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

useMemoは、関数と依存関係の配列を受け取ります。

依存関係は、関数の引数と同様に機能します。 依存関係のリストは、useMemoが監視する要素です。変更がない場合、関数の結果は同じままです。 それ以外の場合は、関数を再実行します。 それらが変更されない場合、コンポーネント全体が再レンダリングされるかどうかは関係ありません。関数は再実行されず、代わりに保存された結果を返します。 これは、ラップされた関数が大きくて高価な場合に最適です。 これがuseMemoの主な用途です。

useMemoの例を作成する

これは、2つの計算コストの高い関数を使用するアイテムの配列にuseMemoを使用する抽象的な例です。

const List = React.useMemo(() => 
  listOfItems.map(item => ({
    ...item,
    itemProp1: expensiveFunction(props.first),
    itemProp2: anotherPriceyFunction(props.second) 
  })), [listOfItems]
)

上記の例では、useMemo関数は最初のレンダリングで実行されます。 useMemoは最初のレンダリングで実行されるため、高価な関数が完了するまでスレッドをブロックします。

useEffectは、高価な関数が終了してエフェクトが発生するまでローディングスピナーをレンダリングできるため、最初はuseEffectほどきれいには見えません。

ただし、後続のレンダリングでは、listOfItemsが変更されない限り、高価な関数を再度実行する必要はありません。 useMemoは、各関数の戻り値を「記憶」します。

これらの高価な関数が瞬時にレンダリングされるように見えます。 これは、高価な同期機能が1つか2つある場合に理想的です。

いつ使用するかuseMemo

最初にコードを記述してから、コードを再検討して、最適化できるかどうかを確認してください。 アプリケーションにuseMemoを頻繁に実装すると、パフォーマンスが低下する可能性があります。

useMemoの実装を検討している場合は、プロファイリングツールを使用して、コストのかかるパフォーマンスの問題を特定できます。 高価は、多くのリソース(メモリなど)を消費していることを意味します。 レンダリング時に関数で十分な数の変数を定義している場合は、useMemoでメモ化するのが理にかなっています。

仕事に適切なフックを使用する

useMemoの他に、useCallbackuseRefuseEffectもあります。

useCallbackフックはuseMemoに似ていますが、メモ化された関数を返しますが、useMemoには値を返す関数があります。

依存関係の配列が指定されていない場合、メモ化の可能性はなく、レンダリングごとに新しい値が計算されます。 その場合、useRefフックを使用できます。 useMemouseRefよりも優れている点は、依存関係が変更された場合に再メモ化することです。

useMemoに副作用や非同期呼び出しを発生させたくないでしょう。 そのような場合は、useEffectを使用する必要があります。

結論

この記事では、useMemoフックと、それをReactアプリケーションで使用するのが適切な場合について説明しました。

useMemoは、高価な関数を「記憶」し、アプリケーションに変更が生じるたびに再レンダリングされないようにすることで、アプリケーションのパフォーマンスを向上させることができます。

このフックを使用するとパフォーマンスを向上させることができますが、使いすぎるとアプリケーションの速度が低下する可能性もあります。 フックを使用すればするほど、アプリケーションはより多くのメモリを割り当てる必要があります。

Reactのベストプラクティスの詳細については、DigitalOceanの How To Code inReact.jsシリーズ全体に従ってください。

モバイルバージョンを終了