Help us understand the problem. What is going on with this article?

React の useMemo と useCallback がよくわからなかったので調べたメモ

More than 1 year has passed since last update.

useCallback とは

https://ja.reactjs.org/docs/hooks-reference.html#usecallback

メモ化されたコールバックを返します。

useMemo とは

https://ja.reactjs.org/docs/hooks-reference.html#usememo

メモ化された値を返します。

わかるようなわかないような感じだったので挙動を確認するコードを書きました。

コード

import * as React from "react";
import { useCallback, useMemo, useState } from "react";

let tmpHandleClick: () => void;
let tmpHandleClick2: () => void;

export const Component: React.FC = () => {
  const [count, setCount] = useState(0);
  const double = useMemo(() => {
    console.log("double が計算された。");
    return count * 2;
  }, [count]);

  const handleClick = useCallback(() => {
    setCount(prev => prev + 1);
  }, []);
  if (tmpHandleClick !== handleClick) {
    console.log("handleClick が生成された。");
  }
  tmpHandleClick = handleClick;

  // ----------------------

  const [count2, setCount2] = useState(0);
  const dobule2Func = (i: number) => {
    console.log("double2 が計算された。");
    return i * 2;
  };
  const double2 = dobule2Func(count2);

  const handleClick2 = () => {
    setCount2(count2 + 1);
  };
  if (tmpHandleClick2 !== handleClick2) {
    console.log("handleClick2 が生成された。");
  }
  tmpHandleClick2 = handleClick2;

  return (
    <div>
      <p>state: {count}</p>
      <p>double: {double}</p>
      <button onClick={handleClick}>handleClick</button>
      <br />
      <p>state2: {count2}</p>
      <p>double2: {double2}</p>
      <button onClick={handleClick2}>handleClick2</button>
    </div>
  );
};

動かしてみた結果

初期表示時

スクリーンショット 2019-07-27 18.31.31.png

初回なのですべてのログが表示される。

handleClick 押下時

スクリーンショット 2019-07-27 18.32.41.png

handleClick は新たに生成されない。
handleClick は useCallbackの第2引数に空配列を与えているので初期表示時にのみ生成される。
useCallback は第2引数の配列に含まれる値に変化があった時のみ関数を新しく生成するため。

handleClick2 押下時

スクリーンショット 2019-07-27 18.33.01.png

useMemo の 第2引数に渡している count に変更がないため double は計算されない。

まとめ

react の component が render されると、毎回、component の中身がすべて再実行されるが、
useMemo, useCallback を使うと必要ない再計算、再生成が行われない。

という当たり前のことが実際に動かしたことで腹落ちしました。

k_7016
gunosy
情報キュレーションサービス「グノシー」や「ニュースパス」の開発・運営を通じて、情報を世界の人に最適に届けていきます。
http://gunosy.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away