0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Reactの不要な再レンダリングを防ぐ

Posted at

はじめに

この記事はReactの不要な再レンダリングを防ぐ,React.memouseCallback についての備忘録です.

React.memo

React.memoは,コンポーネントをメモ化しておくことで不要な再レンダリングを防ぎます.
具体的には,propsが変わらない限り,コンポーネントを再レンダリングしません

例:以下のコードでは,Child2コンポーネントがメモ化されています.
通常,stateが更新されると親が再レンダリングされ,子コンポーネントも再レンダリングされます.
そのため,countやtoggleが変更されたとき,Child1は再レンダリングされます.
一方で,メモ化されたChild2はpropsであるcountが変更されない限り再レンダリングはされません.
つまり,渡されているprops以外(ここではtoggle)が変化した時の親コンポーネントの再レンダリングによる,子コンポーネントの不要なレンダリングを防ぐことができます.

import React, { useState, memo } from "react";

const Child1 = ({ count }) => {
  console.log("メモされていないChild1が再レンダリングされました");
  return <div>カウント: {count}</div>;
};

const Child2 = memo(({ count }) => {
  console.log("メモ化されたChild2が再レンダリングされました");
  return <div>カウント: {count}</div>;
});
const Parent = () => {
  const [count, setCount] = useState(0);
  const [toggle, setToggle] = useState(false);

  return (
    <>
      <button onClick={() => setCount(count + 1)}>カウント増加</button>
      <button onClick={() => setToggle(!toggle)}>トグル</button>
      <Child1 count={count} />
      <Child2 count={count} />
    </>
  );
};

useCallback

useCallbackは関数をメモ化します.React.memoと使うことで不要な再レンダリングを防ぐことができます.
前提として,stateの更新等で再レンダリングされるときには,コンポーネント内の関数も再生成されます.
例:以下のコードでは,countが更新されるとき
countを更新→Parentが再レンダリング→handleClickの再生成
となります.そのため,ChildコンポーネントをReact.memoでメモ化していても,渡されているpropsが変化しているので,Childコンポーネントは再レンダリングされます.

import React, { useState, useCallback, memo } from 'react';

const Child = memo(({ onClick }) => {
  console.log('Childが再レンダリングされました');

  return (
    <div>
      <button onClick={onClick}>子のボタン</button>
    </div>
  );
});

const Parent = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    console.log('子のボタンがクリックされました');
  }

  return (
    <div>
      <h2>カウント: {count}</h2>
      <button onClick={() => setCount((prev) => prev + 1)}>カウント増加</button>

      <Child onClick={handleClick} />
    </div>
  );
};

ここで,useCallbackを使用し関数をメモ化しておくことで,再レンダリングを防ぐことができます.
以下のコードでは,handleClickuseCallbackでメモ化しています.これにより,
countを更新 → Parentが再レンダリング → handleClickはメモ化されているので再生成されない.
となります.つまり,Childコンポーネントのpropsの変化を防いでいるため,結果,Childコンポーネントは再レンダリングされません.

import React, { useState, useCallback, memo } from 'react';

const Child = memo(({ onClick }) => {
  console.log('Childが再レンダリングされました');

  return (
    <div>
      <button onClick={onClick}>子のボタン</button>
    </div>
  );
});

const Parent = () => {
  const [count, setCount] = useState(0);

   // useCallback を使うことで、関数の参照が変わらなくなる
  const handleClick = useCallback(() => {
    console.log('子のボタンがクリックされました');
  }, []);

  return (
    <div>
      <h2>カウント: {count}</h2>
      <button onClick={() => setCount((prev) => prev + 1)}>カウント増加</button>

      <Child onClick={handleClick} />
    </div>
  );
};

まとめ

  • React.memoはコンポーネントをメモ化
  • useCallbackは関数をメモ化

おわりに

この記事は以下の記事を参考にさせていただいています.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?