はじめに
Reactでmemo化することで何がいいことがあるのか。
それを挙動を確かめて確認したことのアプトプットとして記事を残す。
結論
memo化をするとReactのルールの
「親コンポーネントがレンダリングされると、子コンポーネントもレンダリングされる」
ということを防ぐことができるようになります。
状態
親コンポーネント
import { useState } from "react";
import { ChildArea } from "./ChildArea";
import "./App.css";
function App() {
const [text, setText] = useState("");
const [isToggle, setIsToggle] = useState(false);
const onChangeText = (e) => setText(e.target.value);
const changeToggle = () => setIsToggle(!isToggle);
return (
<>
<input value={text} onChange={onChangeText} type="text" />
<br />
<br />
<button onClick={changeToggle}>表示</button>
<ChildArea open={isToggle} />
</>
);
}
export default App;
下記のような子コンポーネントにしていて、あえて大きめの回数のループが回るというコストが高いこコンポーネントとしています。
export const ChildArea = ({ open }) => {
const style = {
width: "100%",
height: "200px",
backgroundColor: "red",
};
const data = [...Array(2000).keys()];
data.forEach((d) => {
console.log("hoge");
});
return (
open && (
<div style={style}>
<p>子コンポーネント</p>
</div>
)
);
};
メモ化する前
親コンポーネントがレンダリングされると、子コンポーネントもレンダリングされるという仕組み上、親コンポーネントのstateが更新された時に子コンポーネントが再レンダリングされてループが走っています。
メモ化すると
下記のように子コンポーネントをmemo化します。
するとこんな感じで親コンポーネントのレンダリングによっての子コンポーネントのレンダリングを防ぐことができます。
import { memo } from "react";
export const ChildArea = memo(({ open }) => {
const style = {
width: "100%",
height: "200px",
backgroundColor: "red",
};
const data = [...Array(2000).keys()];
data.forEach((d) => {
console.log("hoge");
});
return (
open && (
<div style={style}>
<p>子コンポーネント</p>
</div>
)
);
});
まとめ
メモ化をすることで不要なレンダリングを防ぐことができます。
小さなアプリケーションではそこまでコストになることにはないと思いますが注意したいと思います。
逆に親コンポーネントがレンダリングされたら、子コンポーネントもレンダリングして欲しいこともあるかと思います。
このルールを覚えた上で活用していきたいところです。
余談ですが、React!9ではuseMemoとかは使わなくて良くなったような...