☘️

useMemo()を整理してみた

2022/04/29に公開

これは何か?

React初学者が 「useMemo()」 について学習内容をまとめた記事です。
今回は、重い処理がある関数を実装したアプリを例に「useMemo()」を実装してみます。

useMemo()とは何か?

「React.memo」・「useCallback()」と同様に「useMemo」を使用することで、不要な再レンダリングを防ぐことができパフォーマンス向上が期待できる。逆に言えば、これらを使用しなくてもアプリーケーション自体は動作する。

  • 関数の結果を保持するためのフック
  • レンダリングごとに不要な再計算をスキップする

useMemo()の構文

useMemo(() => 値の計算する関数の呼び出し,[値の計算に必要な要素の配列])

開発環境

  • OS:macOS Monterey バージョン12.3.1
  • 言語:TypsScript
  • ライブラリー:React

環境構築

今回はNodeをインストールしている前提で進めます。
環境構築するディレクトリに移動し、「Create-React-App」を使用してReactのアプリ環境を構築します。

$ npx create-react-app@5.0.1 react-typescript-app --template typescript

https://create-react-app.dev/docs/getting-started

You are running `create-react-app` 5.0.0, which is behind the latest release (5.0.1).

We no longer support global installation of Create React App.

Please remove any global installs with one of the following commands:
- npm uninstall -g create-react-app
- yarn global remove create-react-app

The latest instructions for creating a new app can be found here:
https://create-react-app.dev/docs/getting-started/

ファイル構成

react-typescript-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── ts.config.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src
    ├── App.module.scss  
    ├── App.css
    ├── App.tsx
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── serviceWorker.js
    └── setupTests.js|

実装

今回はSassでスタイリングするので、node-sassをインストールします。

$npm install node-sass
App.tsx
import React, { useState } from "react";
import classes from "./App.module.scss";

function App() {
  const [countA, setCountA] = useState<number>(0);
  const [countB, setCountB] = useState<number>(0);

  const calculatedResult = heavyFunction(countA);

  return (
    <div className={classes.app}>
      <h2>useMemo</h2>
      <p>Aをクリックすると「+100」, Bをクリックすると「+1」される</p>
      <p>また、Aは+100されると同時にAの値が2倍された値が表示される</p>
      <div className={classes.itemsWrapper}>
        <div className={classes.items}>
          <p>Aの値:{countA}</p>
          <p>Aが2倍された値:{calculatedResult}</p>
          <button
            onClick={() => {
              setCountA(countA + 100);
            }}
          >
            A(重い処理)
          </button>
        </div>
        <div className={classes.items}>
          <p>Bの値:{countB}</p>
          <button
            onClick={() => {
              setCountB(countB + 1);
              console.log("Bをクリック");
            }}
          >
            B
          </button>
        </div>
      </div>
    </div>
  );
}

//useMemo()を実装した場合としていない場合の違いを確かめるために、Aボタン押した時に重い処理を入れます。
function heavyFunction(count: number) {
  let i = 0;

  while (i < 1000000000) {
    i++;
  }
  console.log("重い処理を実行");
  return count * 2;
}

export default App;

スタイリング

App.module.scss
.app {
  margin-top: 40px;
  text-align: center;
  .itemsWrapper {
    display: flex;
    justify-content: space-around;
    width: 40%;
    margin-left: auto;
    margin-right: auto;
    .items {
      button {
        color: white;
        font-weight: bold;
        cursor: pointer;
        text-align: center;
        width: 150px;
        padding: 15px;
        margin: 10px;
        border-radius: 180px;
        background: #668ad8; 
        box-shadow: 0px 10px gray;
        &:active {
          box-shadow: none;
          position: relative;
          top: 5px;
        }
      }
    }
  }
}

完成画面

では、Bボタンを押した時のログを確認しながら、useMemo()を実装した時としていない時の違いをみていきます。

useMemo()を実装しない場合

Bボタンをクリックしてみます。

heavyFunction関数が実行されるため、Bの値が表示されるまで時間がかかります。

useMemo()を実装した場合

heavyFunctionをuseMemoでラップしてみます。

App.tsx
+ import React, { useMemo, useState } from "react";
- import React, { useState } from "react";

+ const calculatedResult = useMemo(() => {
+ return heavyFunction(countA);
+ }, [countA]);
- const calculatedResult = heavyFunction(countA);

Bボタンをクリックしてみます。

useMemoによりheavyFuncion関数の結果がメモ化されているため、heavyFunction関数は実行されません。
毎回、重い処理が実行される関数をメモ化することでパフォーマンス向上ができます。

最後までお読みいただきあありがとうございました。
もし誤っていることがあれば、ご指摘いただけます幸いです。

参考記事・参考書籍

https://qiita.com/soarflat/items/b9d3d17b8ab1f5dbfed2

https://www.amazon.co.jp/基礎から学ぶ-React-Hooks-asakohattori/dp/486354359X

GitHubで編集を提案

Discussion