top_logo

Reactのコンポーネントで再レンダリングが起こる瞬間3選

2022年 03月 21日

React でコンポーネントの再レンダリングが起こってしまう瞬間を 3 つまとめてみました。


不要な再レンダリングを減らすことは、ブラウザの負荷の改善、ページ速度の向上に繋がりますので参考にしていただけたらと思います。


また、react の文法や useState の記法などについては解説しておりません。

この記事に挙げた再レンダリングを解消する方法については次の記事で解説する予定です。

結論

結論として、再レンダリングが起こる瞬間は次の3つです。


コンポーネントの state が更新されたとき


親コンポーネントの state が更新されたとき


親コンポーネントから渡された props が更新されたとき


解説

それぞれ解説していきます

コンポーネントの state が更新されたとき

基本的でわかりやすいタイミングだと思います。

具体的には以下のコードになります。


ボタンを押すと、count+1 され state で管理している count が更新されます。


このとき再レンダリングが起こり、App 関数のスコープ内の一番上から順番に実行されることになります。

これが最も重要です。


count upボタンを押すたびに App 関数のスコープ内の一番上に戻り、

console.log("Appの再レンダリング")が実行されます。


こちら、ぜひ手元で確認していただけたらと思います。


src/App.js
import React from 'react';
import { useState } from "react"

export const App = () => {
  // count upボタンを押すたびにここに戻る。
  console.log("Appの再レンダリング")
  const [count, setCount] = useState(0)

  const onClickCountUP = () => {
    setCount(preveState => preveState + 1)
  }
  return (
    <div>
      <p>{count}</p>
      <button onClick={onClickCountUP}>count up</button>
    </div>
  )
}

ひとつ目の解説は以上になります。

親コンポーネントの state が更新されたとき

こちらは、ひとつ目のように state が更新されたとき、子供のコンポーネントにまで再レンダリングが起こってしまうということです。


以下のコードでは、App.jsinputにテキストを入力する度に、親コンポーネント(App.js)と子コンポーネント(Child.js)で再レンダリングが起こり、コンソールで以下のように表示されます。


このとき子コンポーネントでは親コンポーネントと同様に、関数のスコープ内の一番上から処理が順番に実行されることになります



src/App.js
import React from 'react';
import { useState } from "react";
import { Child } from "./Child";

export const App = () => {
  // inputにテキストを入力する度にここに戻る。
  console.log("再レンダリング");
  const [text, setText] = useState("");
  const onChangeText = (e) => setText(e.target.value);

  return (
    <div>
      <input value={text} onChange={onChangeText} />
      <Child />
    </div>
  );
};

src/Child.js
import React from 'react';

export const Child = ({ open }) => {
  // App.jsのinputにテキストが入力される度にここに戻る。
  console.log("子供レンダリング");
  return (
        <div>
          <p>子供</p>
        </div>
  );
};

二つ目の解説は以上になります

親コンポーネントから渡された props が更新されたとき

次に親からのpropsが更新された時について解説します。


子コンポーネントでは親から、openという state がpropsとして渡されています。

このopenを boolean として 3 項間演算子で表示を変えています。


親コンポーネントで、表示ボタンを押すたびに親コンポーネントのstateで管理しているopenの値が更新され、子コンポーネントに渡されるpropsが更新されることになります。


これが原因で子コンポーネントで再レンダリングが起こります。


また、親のstateが変更されていて尚且つ、子に渡したpropsが変更されているため再レンダリングが 2 度起こるのではないかと思ってしまいますが、この場合一度しか起こりません。


src/App.js
import React from 'react';
import { useState } from "react";
import { Child } from "./Child";

export const App = () => {
  console.log("再レンダリング");
  const [open, setOpen] = useState(false);
  const OnClickOpen = () => setOpen(!open);

  return (
    <div>
      <button onClick={OnClickOpen}>表示</button>
      <Child open={open} />
    </div>
  );
};
src/Child.js.js
import React from 'react';
import { Fragment } from "react";

export const Child = ({ open }) => {
  console.log("子供レンダリング");
  return (
    <Fragment>
      {open ? (
        <div style={style}>
          <p>子供</p>
        </div>
      ) : null}
    </Fragment>
  );
};

3 つ目の解説は以上になります

感想

次の記事では、再レンダリングを回避する方法について書く予定です。


ここまで読んでくださりありがとうございます。


わかりにくい点、間違っている点などあれば以下にご連絡いただければと思います。


Twitter:  https://twitter.com/naka_ryo_z

Github:  https://github.com/ryotaro-tenya0727

メール:   ryotaro123110@gmail.com

見出しへのリンク

© 2024, written by Nakayama

Powered by Gatsby