React.memoの使い方。パフォーマンスアップ【TypeScript】

プログラミング

Reactでパフォーマンスアップのコツは、不要な再レンダリングを抑えることだよね…。

今回は、Reactのパフォーマンスを悪くする再レンダリングについてです。

▼この記事で理解できる内容は以下になります。

  1. React.memoの使い方
  2. React.memoを使う場合、使わない場合の比較

この記事は、React初心者の方、React.memoについて知りたい方を対象としています。



目次

  1. React.memoってどんな機能?
    • React.memoは使い道
    • React.memoはは最後のレンダリングを記憶している
    • propsの変更のみチェックしている
  2. React.memoの使い方
    • React.memoの基本形
    • React.memoの使用例
    • React.memoの使用した結果
  3. React.memoの使い方まとめ

React.memoってどんな機能?

React.memoはどのようにパフォーマンスアップさせるのかReact公式の内容を見ると参考になります。

React.memoは使い道

頻繁に再レンダリングされるコンポーネントで、書き換える必要のない子コンポーネントがぶら下がっている場合に利用するとパフォーマンスアップにつながる。

React.memoは最後のレンダリングを記憶している

もしあるコンポーネントが同じ props を与えられたときに同じ結果をレンダーするなら、結果を記憶してパフォーマンスを向上させるためにそれを React.memo でラップすることができます。つまり、React はコンポーネントのレンダーをスキップし、最後のレンダー結果を再利用します。
引用元: React公式

前回レンダーされた結果を記憶しているため、同じ内容であれば再レンダリングを行わないためパフォーマンスアップにつながる。

propsの変更のみチェックしている

React.memo は props の変更のみをチェックします。
引用元: React公式

子のコンポーネントでReact.memoが使われている場合、propsの変更のみチェックしているため、変更がない場合は再レンダリングを行わないためパフォーマンスアップにつながる。

React.memoの使い方

React.memoはラップするだけで簡単に利用することができます。

React.memoの基本形

const SampleMemo = React.memo(props => {
  return <p>{props.memo}</p>
});

React.memoの使用例

親コンポーネントにある2つのボタンをクリックし、React.memoを使っている子コンポーネントと使っていない子コンポーネントのレンダリングの動作を確認してみます。

Vue.jsではcomputedが、それに近い動きをします。computed内にあるプロパティに変化がない場合は再レンダリングが行われません。

以下のようなサンプル画面を準備しました。

▼サンプルの画面

React.memo

親コンポーネントに2つのボタンとボタンクリックした時にカウントアップされる値をpropsで受け取る子コンポーネントです。

子コンポーネントは、片方の「NormalCountコンポーネント」は特に何もしていない子コンポーネント。

「MemoCountコンポーネント」は、React.memoを利用した子コンポーネントです。それぞれTypeScriptで書いています。

親コンポーネント

import React, { useState } from 'react'
import NormalCount from './components/NormalCount'
import MemoCount from './components/MemoCount'

export default function App() {
  const [normalCount, setNormalCount] = useState(0)
  const [memoCount, setMemoCount] = useState(0)

  return (
    <div>
      <NormalCount normalCount={normalCount}/>
      <MemoCount memoCount={memoCount}/>
      <button onClick={() => setNormalCount(normalCount + 1)}>NORMAL</button>
      <button onClick={() => setMemoCount(memoCount + 1)}>MEMO</button>
    </div>
  )
}

NormalCountコンポーネント

import React from 'react'

interface NormalProps {
  normalCount: number
}
const NormalCount: React.FC<NormalProps> = (({ normalCount }) => {

  console.log('■ Normal Count')
  return (
    <div>
      <p>normalCount: {normalCount}</p>
    </div>
  )
})

export default NormalCount

MemoCountコンポーネント

import React from 'react'

interface MemoProps {
  memoCount: number
}

const MemoCount: React.FC<MemoProps> = React.memo(({ memoCount }) => {

  console.log('▼ Memo Count')
  return (
    <div>
      <p>memoCount: {memoCount}</p>
    </div>
  )
})

export default MemoCount

React.memoの使用した結果

「MEMOのボタン」を押下した場合は、NormalCountコンポーネントの方の値に影響がなくても再レンダリングされています。

逆に「NORMALのボタン」を押下した場合は、React.memoでラップされたMemoCountコンポーネントのpropsの値に影響がないため再レンダリングされていないのがわかります。

React.memoの使い方まとめ

今回のように軽いコンポーネントの場合は、パフォーマンスに影響がでることはないと思いますが、レンダリングに時間がかかるコンポーネントなどで毎回再レンダリングされると、パフォーマンスに影響します。

頻繁に値が変化するようなアプリの場合は、React.memoの利用も考えながらコンポーネントを作っていきたいですね。

当サイトで申込の多いプログラミングスクール

TechAcademyの無料体験
マンツーマンでオリジナルアプリの作成ができるテックアカデミーは人気が高いプログラミングスクール。
Webエンジニア輩出実績トップクラスの【ポテパンキャンプ】
転職に強く本気でエンジニア転職を目指す人におすすめ。難易度が高いため身につくスキルも高く企業からの評価も高いのが特徴。
CodeCamp無料体験
講師を選択できるのが特徴のコードキャンプ。チャットでの質問ができないと言われていますが、オプションでチャットサポートを選択できるのがあまり知られていない。講師の評判が高いため質問しながらどんどん進みたい人向け。