Reactのコンポーネントで再レンダリングが起こる瞬間3選
React でコンポーネントの再レンダリングが起こってしまう瞬間を 3 つまとめてみました。
不要な再レンダリングを減らすことは、ブラウザの負荷の改善、ページ速度の向上に繋がりますので参考にしていただけたらと思います。
また、react の文法や useState
の記法などについては解説しておりません。
この記事に挙げた再レンダリングを解消する方法については次の記事で解説する予定です。
結論として、再レンダリングが起こる瞬間は次の3つです。
コンポーネントの state が更新されたとき
親コンポーネントの state が更新されたとき
親コンポーネントから渡された props が更新されたとき
それぞれ解説していきます
基本的でわかりやすいタイミングだと思います。
具体的には以下のコードになります。
ボタンを押すと、count
が+1
され state
で管理している count
が更新されます。
このとき再レンダリングが起こり、App 関数のスコープ内の一番上から順番に実行されることになります。
これが最も重要です。
count up
ボタンを押すたびに App 関数のスコープ内の一番上に戻り、
console.log("Appの再レンダリング")
が実行されます。
こちら、ぜひ手元で確認していただけたらと思います。
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 が更新されたとき、子供のコンポーネントにまで再レンダリングが起こってしまうということです。
以下のコードでは、App.js
のinput
にテキストを入力する度に、親コンポーネント(App.js
)と子コンポーネント(Child.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>
);
};
import React from 'react';
export const Child = ({ open }) => {
// App.jsのinputにテキストが入力される度にここに戻る。
console.log("子供レンダリング");
return (
<div>
<p>子供</p>
</div>
);
};
二つ目の解説は以上になります
次に親からのprops
が更新された時について解説します。
子コンポーネントでは親から、open
という state がprops
として渡されています。
このopen
を boolean として 3 項間演算子で表示を変えています。
親コンポーネントで、表示ボタンを押すたびに親コンポーネントのstate
で管理しているopen
の値が更新され、子コンポーネントに渡されるprops
が更新されることになります。
これが原因で子コンポーネントで再レンダリングが起こります。
また、親のstate
が変更されていて尚且つ、子に渡したprops
が変更されているため再レンダリングが 2 度起こるのではないかと思ってしまいますが、この場合一度しか起こりません。
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>
);
};
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