Reactの再レンダリングとメモ化の話
公開日:
タグ:
- #Next.js
- #React
Reactのレンダリングについてあまり理解できておらず、曖昧なまま使っていた部分もあったので、改めて調べ直しました。
Reactが再レンダリングを行うタイミングは3つ
そもそも、Reactが再レンダリングが行われるパターンは3つしかありません。
1. stateが変わった時
'use client';
import { useState } from 'react';
import styles from './page.module.scss';
export default function Parent() {
console.log('Parent component rendered');
const [text, setText] = useState('');
return (
<>
<h2 className={styles.title}>Re-Rendered</h2>
<input
className={styles.input}
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
</>
);
}
上記の場合 text が更新されるたびに再レンダリングが走ります。
2. propsが変わった時
'use client';
import { Child } from '@/components/Child';
import { useState } from 'react';
import styles from './page.module.scss';
export default function Parent() {
console.log('Parent component rendered');
const [count, setCount] = useState(0);
return (
<>
<h2 className={styles.title}>Re-Rendered</h2>
<button
className={styles.button}
type="button"
onClick={() => setCount(count + 1)}
>
Increment Count
</button>
<Child count={count} />
</>
);
}
export const Child = ({ count }: { count: number }) => {
console.log('Child component rendered');
return <div>{count}</div>;
}; 親コンポーネントで Child コンポーネントに count という値を渡している。なので、 count が変更されると Child が再レンダリングされる。
3. 親が再レンダリングした時
'use client';
import { Child } from '@/components/Child';
import { useState } from 'react';
import styles from './page.module.scss';
export default function Parent() {
console.log('Parent component rendered');
const [count, setCount] = useState(0);
return (
<>
<h2 className={styles.title}>Re-Rendered</h2>
<button
className={styles.button}
type="button"
onClick={(e) => setCount(count + 1)}
>
Increment Count
</button>
<Child />
</>
);
} export const Child = () => {
console.log('Child component rendered');
return <div>Child Component</div>;
}; 上記の例では、 Childコンポーネントには props を渡していません。ですが、 Parentコンポーネントで
state を更新しているため、親コンポーネントの再レンダリングに合わせて、Childコンポーネントも再レンダリングされます。
メモ化とは
この「不要な再レンダリング」を防ぐために、Reactにはメモ化という仕組みがあります。
メモ化とは簡単に言うと、
前回と同じ結果になるのであれば、処理をスキップする
という最適化の考え方です。
今回の例でいうと、3番目の親が最レンダリングされることで子も再レンダリングパターンです。
- Child は props を受け取っていない
- 表示内容も変わっていない
このような「見た目が変わらないのに再レンダリングされるコンポーネント」に対して、
- 前回と状態が変わっていないなら再レンダリングしない
という仕組みを使えるのが、Reactのメモ化です。
React では次のような方法でメモ化を行います。
React.memo:コンポーネントの再レンダリングをスキップするuseMemo:値の再計算を防ぐuseCallback:関数の再生成を防ぐ
ただし、これらは「再レンダリングを完全に止める」ためのものではなく、
必要な再レンダリングだけを残し、不要なものを減らすための最適化
という位置づけの仕組みです。
詳しい内容はまた次回。