useMemoとuseCallback / React Hooks – React入門

useMemoとuseCallback / React Hooks – React入門

連載目次 : React入門
前回の記事 : useEffect / React Hooks
次回の記事: useRef

Reat Hooksのパフォーマンスチューニングで重要なuseMemouseCallbackについて解説を行います。

functionコンポーネントの再描画でも解説したとおり、functionコンポーネントは高い頻度で再描画が行われます。

同じ結果を返す処理に関しては初回のみ処理を実行しておき、2回目以降は前回の処理結果を呼び出すことで毎回同じ処理を実行しなくてよくなります。

これはプログラミングではメモ化と呼ばれるテクニックで、それをReact Hooks上で簡単に利用できるのがuseMemouseCallbackです。

useMemo

useMemoも他のHooks APIと同様にReactのimport時に読み込むことで利用できるようになります。

import React, { useMemo } from 'react';

そして、functionコンポーネントのトップレベルの位置で以下の宣言を行いメモ化したい変数を定義します。第2引数にはuseEfectと同様に依存変数を配列で指定しておくことで依存変数に変更があった場合には再処理が実行されるようになります。

const メモ化したい変数 = useMemo(() => {
  // 実行したい処理を記述
  return メモ化したい変数
},[依存変数を配列で記述])

例えば受け取ったタイムスタンプを日付に変換している次のコンポーネントを見てみましょう。

const Foo = ({timestamp}) => {
  const dateObj = new Date(timestamp)
  const dateString = `${dateObj.getFullYear()}年${dateObj.getMonth() + 1}月${dateObj.getDate()}日` // YYYY年MM月DD日
  return (
    <p>日付:{dateString}</p>
  )
}

上記のコードですと日付オブジェクトの作成や、日付オブジェクトから文字列を作成する処理がfunctionコンポーネントの再描画のたびに実行されてしまいます。

これをuseMemoを利用して書き直してみましょう。

const Foo = ({timestamp}) => {

  const dateString = useMemo(()=>{
    const dateObj = new Date(timestamp)
    return `${dateObj.getFullYear()}年${dateObj.getMonth() + 1}月${dateObj.getDate()}日`
  },[timestamp])

  return (
    <p>日付:{dateString}</p>
  )
}

useMemo内で日付文字列を生成するように変更しましたので、日付文字列を生成する処理は初回もしくはtimestampが変更された際にしか実行されなくなります。

useCallback

useCallbackはメモ化したコールバック関数を返すHooks APIです。

コールバック関数を利用したイベント設定はReactのイベント設定で解説しましたが、useCallbackを利用しない場合はコールバック関数はfunctionコンポーネントの再描画のたびに新しい関数インスタンスを生成してイベントとしてバインドされていきます。

const MyComponent = () => {
  // コールバック関数
  const handleInput= (e) => {
    // イベント発生時に実行したい処理
    console.log(e.target.value)
  }
 
  return (
    <div>
      <input type="button" defaultValue="" onClick={handleInput}/>
    </div>
  )
}

useCallbackを利用することで関数をメモ化して新しい関数インスタンスを生成せずに再描画後のイベントとして再利用を行います。

onst MyComponent = () => {
  // コールバック関数
  const handleInput= useCallback((e) => {
    // イベント発生時に実行したい処理
    console.log(e.target.value)
  },[])
 
  return (
    <div>
      <input type="button" defaultValue="" onClick={handleInput}/>
    </div>
  )
}

コールバック関数を作成する場合には極力useCallbackを利用するのがよいでしょう。

次回は再描画を抑制するために重要なHooks API であるuseRefについて解説を行います。

連載目次 : React入門
前回の記事 : useEffect / React Hooks
次回の記事: useRef