プログラミングマガジン

プログラミングを中心にIT技術をできるだけわかりやすくまとめます。

  • ホーム
  • React
  • 【React】「useMemo/useCallback」について
 
 
     
  • サーバー言語  
    • Python
    • Ruby
    • PHP
    • SQL
  •  
  • インフラ  
       
    • AWS
    •  
    • 基本
    • Git
  • Web
       
    • Web開発
    • JavaScript
    • Vue.js
    • React
  •  
  • 設計  
       
    • 実装設計
    • DB設計
  • 問い合わせ
  

【React】「useMemo/useCallback」について

07.22

  • miyabisan2
  • コメントを書く

この記事は2分で読めます

結論

別コンポーネントにpropsで渡す関数はuseCallbackを使い、コンポーネント内で計算結果を値として使う関数に対してはuseMemoを使う。

前提

「useMemoは値を返す。useCallbackは関数を返す。」という前提を押さえておくことが重要。

useMemo

メモ化された値を返すフックです。計算結果を保持しそれを再利用する手法のこと。コンポーネントの再描画時の値の再計算の無駄がなくなりパフォーマンスが上がります。

ちなみに、useMemoはmemoと違ってあらゆる値をメモ化することが可能なので極端な話jsxなどもメモ化することができます。

構文

1
useMemo(メモ化する値を計算するコールバック関数,その計算が依存する変数)

第一引数はコールバック関数を指定しますが、「コールバック関数自体」をメモ化しているのではなく「コールバック関数が返す値」をメモ化します。

使い所

例えば、値を更新する処理だけで呼んでほしい関数があった場合に、入力処理まで呼ばれるようになっている場合など。

実装例

bai関数は関係のないCount2の値が更新される場合は呼ばれません。(useEffectなどで書くと呼ばれる度に描画されることになります。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React,{useState,useMemo} from'react';
 
function App(){
  const [count1,setCount1] = useState(0);
  const [count2,setCount2] = useState(0);
  const bai = count => {
    return count*2;
  };
const baiCount = useMemo(() => bai(count1), [count1]);
 
  return(
    <div>
      <p>Count1:{count1}</p>
      <p>DubbleCount:{baiCount}</p>
      <button onClick={()=>setCount1(count1+1)}>increment1</button>
      <p>Count2:{count2}</p>
      <button onClick={()=>setCount2(count2+1)}>increment2</button>
    </div>
  );
}
 
export default App;

useCallback

関数を子コンポーネントに渡した際、親コンポーネントがレンダリングされると子のpropsが別物とみなされて子も再レンダリングされてしまいます。そんな場合でもメモ化したい際に使えるフックです。

React.memoと組み合わせる。

メモ化されたコールバック関数を返すフックです。生成したコールバック関数を保持できるためコンポーネントの再描画時に関数を再利用できます。

アロー関数で書いた関数はレンダリングのたびに毎回違う関数を生成します。なので、propsで関数を渡した際に毎回値が変わっていると判定されてしまって、memo化したとしても再レンダリングが行われることになります。

React.memoと併用すると、React.memoでメモ化したコンポーネントにuseCallbackでメモ化したコールバック関数をPropsとして渡すことで、コンポーネントの不要な再描画をスキップすることができパフォーマンスが上がります。

カスタムフックでは適用が必須

なお、カスタムフックで関数を定義する場合は基本的にuseCallbackを適用することが推奨されます。なぜならプロジェクトのさまざまな箇所で利用し、あるコンポーネントがpropsで関数を渡してないとしても別コンポーネントでは渡す可能性があるためです。

構文

第一引数の関数がコールバック関数になりメモ化されます。

1
useCallback(コールバック関数(メモ化),[依存しているstate])

第二引数(依存配列)

第二引数が空配列になっていた場合は初回レンダリングに生成した関数をReact内で保持するという意味になります。

もし依存しているstateがある場合は指定するとそのstateが更新されるたびに関数が再生成されます。指定しないとずっと同じstateを保持し続けてしまうので注意です。

実装例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React,{useState,useCallback,useEffect,memo} from'react';
 
const Button = memo(({id,onClick})=>{
  useEffect(()=>{console.log(`render${id}`);});
  return <button onClick={onClick}>{id}</button>;
});
 
function App(){
  const [count1,setCount1] = useState(0);
  const increment1 = useCallback(()=> setCount1(count1 + 1),[count1]);
  // const increment1 = ()=> setCount1(count1 + 1); ←これを使うとbutton2をクリックした場合でもincrement1の方のコンポーネントが再描画される。
  const [count2,setCount2]=useState(0);
  const increment2 = useCallback(()=> setCount2(count=>count+1),[]);
 
  return(
    <div>
      <p>{count1}</p>
      <Button id={'Increment1'} onClick={increment1}/><p>{count2}</p>
      <Button id={'Increment2'} onClick={increment2}/>
    </div>
  );
}
 
export default App;

useMemoとuseCallbackの使い分け

useMemoは単純に計算結果を保持するために使います。(Vue.jsのcomputedに近いイメージです。)

useCallbackは、React.memoを使ったとしても、即時関数をpropsとして渡すと再レンダリングが行われてしまいます。(React.memoを使った際のアンチパターンのようです。)即時関数をuseCallbackにラップすることで、別コンポーネントに渡す際に再レンダリングが起こらないようにする用途で使えます。

むしろ、React.memoと併用して使う以外の用途はない。memo化されてないコンポーネントに対してuseCallbackでメモ化したpropsを渡しても結局再レンダリングされてしまうため。

また、カスタムフックを使った場合は基本的にはpropsで渡されることも想定して汎用性を持たせるためにuseCallbackを使うことが推奨されます。

スポンサーリンク
  • 2021 07.22
  • miyabisan2
  • コメントを書く
  • React
  • Tweets Twitter
  • このエントリーをはてなブックマークに追加
  • LINEで送る

関連記事

  1. 2021 02.08

    【Redux】Reduxの基本と動作の仕組み、3原則(単一情報源、イミュータブル、純粋関数)

  2. 2021 02.14

    【Redux】「redux-saga」で非同期処理

  3. 2021 06.20

    【JavaScript】「APIモックライブラリ」の比較

  4. 2021 02.27

    【React】「useRef」の実践的な使い方

  5. 2021 05.04

    【React/Redux】「Redux Tool Kit」の導入(createSlice)

  6. 2021 02.11

    【React】「API」の実行をテストしたい場合(直接呼ぶ、axiosのjestモック、mswを使う。)

  • コメント ( 0 )
  • トラックバック ( 0 )
  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

返信をキャンセルする。

【業務知識】「端末の種類(CAT、CCT)」について

【Redux】新しいStoreとの接続方法

RETURN TOP

著者プロフィール

エンジニア歴10年で過去に業務系、Webデザイン、インフラ系なども経験あります。現在はWeb系でフロントエンド開発中心です。

詳細なプロフィールはこちら

スポンサーリンク

カテゴリー

  • Android
  • AngularJS
  • API
  • AWS
  • C++
  • CSS
  • cursor
  • C言語
  • DDD
  • DevOps
  • Django
  • Docker
  • Figma
  • Git
  • GitLab
  • GraphQL
  • gRPC
  • Hasura
  • Java
  • JavaScript
  • Kubernetes
  • Laravel
  • linux
  • MySQL
  • Next.js
  • nginx
  • Node.js
  • NoSQL
  • Nuxt.js
  • Oracle
  • PHP
  • Python
  • React
  • Redux
  • Rspec
  • Ruby
  • Ruby on Rails
  • Sass
  • Spring Framework
  • SQL
  • TypeScript
  • Unity
  • Vue.js
  • Webサービス開発
  • Webデザイン
  • Web技術
  • インフラ
  • オブジェクト指向
  • システム開発
  • セキュリティ
  • その他
  • データベース
  • デザインパターン
  • テスト
  • ネットワーク
  • プログラミング全般
  • マイクロサービス
  • マイクロソフト系技術
  • マルチメディア
  • リファクタリング
  • 副業
  • 未分類
  • 業務知識
  • 生成AI
  • 設計
  • 関数型言語
RETURN TOP

Copyright ©  プログラミングマガジン | プライバシーポリシー