React入門者へおすすめ動画&書籍おすすめ!

フロントエンド入門者へおすすめ動画&書籍おすすめ!

JavaScript React

ReactでuseMemoとReact.memoを使ってコンポーネントと変数をメモ化してみた

0
0

こんにちわ。

 

Reactでは、値に変更が加わったときに何かしらの動作を発動させる方法がいくつかあります。

 

その中で、useMemoとuseEfectがあるんですけれども、この二つは似てるようで全然違います。

 

基本的には、アプリの機能を実装するのはuseEfextを使って、アプリのパフォーマンスを向上させる場合にusdeMemoを使います。

 

なるべくuseMemoは使わない方法で実装するのがFacebookの方針のようです。

 

下記の記事には、useEfextとuseMemoに関する違いに、下記のように書かれていますが、

 

useEffect値が変更されたとき(またはコンポーネントが最初にレンダリングされたとき)に(非同期に)何か実行できます。「何かをする」は何でもかまいません。API呼び出しを行ったり、状態を設定したりする場合があります。または、他の何か。

useMemoはまったく異なります。これを使用すると、必要な場合にのみ計算し、それを(同期して)使用できます

 

今日の記事では、Reactで値をmemo化させる方法を、React.memoと、useMemoを使って実装してみたいと思います。

 

ちなみにですが、この記事ではReact.memoと、useMemoの違いについては言及しません。

 

どんなときにuseMemoを使うの?

重要なのは、コードが useMemo に依存していてはいけないということです。

 

言い換えれば、useMemo の呼び出しを直接の関数呼び出しに置き換えても、

 

アプリケーションの動作はパフォーマンスを除いて何も変わらないようにする必要があります。

 

最も簡単な方法は、まず useMemo を使わずにコードを書き、必要に応じて追加していくことです。

 

useMemo を理解するために、どのような場合に使用するのか、

 

次の例を見てみましょう。まず、useMemo を使わないこのコードを見てください。

 

import React, {useState} from 'react';

function App() {
  const [length, set_length] = useState(3);
  const [name, set_name] = useState('John Doe');

  return (
    <>
      <input value={name} onChange={e => set_name(e.target.value)} />
      <NameDisplay name={name}/>
      <hr />
      <input value={length} onChange={e => set_length(Number(e.target.value))} />
      <FibDisplay length={length} />
    </>
  );
}

function FibDisplay({length}) {
  console.log('Calculating numbers & rerendering...');
  const numbers = [1, 1];
  for (let i = 2; i < length; i++) {
    numbers[i] = numbers[i - 1] + numbers[i - 2];
  }

  return <p>{length} numbers of the fibonacci sequence: {numbers.join(', ')}</p>;
}

function NameDisplay({name}) {
  console.log('Rerendering name...');
  return <p>Your name is {name}</p>;
}

export default App;

 

この小さなアプリは名前と数字を入力して、その計算結果を返して画面に出力します。

 

NameDisplayコンポーネントとFibDisplayの両方が、名前か数字どちらかだけでもを更すると、再レンダリング(および高価な計算の実行)されます。

 

これを修正する方法があります。

 

import React, {useState, useMemo} from 'react';

function App() {
  const [length, set_length] = useState(3);
  const [name, set_name] = useState('John Doe');

  return (
    <>
      <input value={name} onChange={e => set_name(e.target.value)} />
      <NameDisplay name={name}/>
      <hr />
      <input value={length} onChange={e => set_length(Number(e.target.value))} />
      <FibDisplay length={length} />
    </>
  );
}

function FibDisplay({length}) {
  const numbers = useMemo(() => {
    console.log('Calculating numbers...');
    const result = [1, 1];
    for (let i = 2; i < length; i++) {
      result[i] = result[i - 1] + result[i - 2];
    }
    return result;
  }, [length]);

  return <p>{length} numbers of the fibonacci sequence: {numbers.join(', ')}</p>;
}

const NameDisplay = React.memo(function ({name}) {
  console.log('Rerendering name...');
  return <p>Your name is {name}</p>;
});

export default App;

 

FibDisplayでuseMemoが使われていることに注目すると、高価な計算を、長さが変化したときにのみ実行される関数に包んでいます。

 

コンポーネントはまだ再レンダリングされますが、高価な計算は必要なとき以外は実行されません。

 

次に、NameDisplayコンポーネントがReact.memoでラップされていることに注目すると、React.memoは、コンポーネント全体を記憶する方法です。

 

これは、propsが変更されたときにのみ再レンダリングされるので、私たちの問題を完全に解決します。

 

*コードなど参考にした記事

Pocket
LinkedIn にシェア

React入門者へおすすめ動画&書籍おすすめ!

フロントエンド入門者へおすすめ動画&書籍おすすめ!

  • この記事を書いた人
  • 最新記事

藤沢瞭介(Ryosuke Hujisawa)

りょすけと申します。18歳からプログラミングをはじめ、今はフロントエンドでReactを書いたり、AIの勉強を頑張っています。off.tokyoでは、ハイテクやガジェット、それからプログラミングに関する情報まで、エンジニアに役立つ情報を日々発信しています!

-JavaScript, React

Copyright© off.tokyo , 2021 All Rights Reserved Powered by AFFINGER5.