Reactのレンダー・マウント・再レンダー・アンマウントの違い
この章の目次開く
Reactのフック(useState・useEffect など)を正しく使うには、レンダーとマウントの違いを理解しておく必要があります。
この2つは混同されやすいですが、指しているものがまったく異なります。
学習者「レンダー」と「マウント」って同じ意味じゃないの…?なんとなくで使ってたけど、違うものなの?
まず結論
Reactで「レンダーされた」と「マウントされた」は同じ意味ではありません。レンダーは関数が呼ばれてJSXを計算すること、マウントはその結果が初めてDOMに入ることです。
| 状況 | 起きること |
|---|---|
| 初めて画面に出る | 初回レンダー → DOMに挿入 → マウント後の useEffect |
| stateが変わる | 再レンダー → DOMの差分更新 |
| propsが変わる | 再レンダー → DOMの差分更新 |
| 条件分岐で消える | アンマウント → useEffect のクリーンアップ |
この区別が分かると、useEffect(..., []) がなぜ初回だけ実行されるのか、state更新でなぜ関数全体が再実行されるのかを説明できます。
4つの用語
| 用語 | 意味 |
|---|---|
| レンダー | コンポーネントの関数が呼ばれてUIを計算すること |
| マウント | コンポーネントが最初にDOMに追加されること |
| 再レンダー | 2回目以降のレンダー |
| アンマウント | コンポーネントがDOMから取り除かれること |
レンダーとは
レンダーとは、Reactがコンポーネント関数を呼び出してUIの計算結果(JSX)を得ることです。
function Greeting({ name }: { name: string }) {
// この関数が呼ばれること自体が「レンダー」
return <p>こんにちは、{name}さん</p>;
}レンダーのたびに関数全体が再実行されます。const・let で定義したローカル変数も、すべて作り直されます。
レンダーが起きるタイミング
- 自身のstateが変わったとき(
useStateの更新関数を呼んだとき) - 親コンポーネントが再レンダーされたとき(子も連動して再実行される)
function Counter() {
const [count, setCount] = useState(0);
console.log('rendered'); // ボタンを押すたびにここが実行される
return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
}ボタンを押すたびに Counter 関数が再実行され、console.log('rendered') が出力されます。
マウントとは
マウントとは、コンポーネントが初めてDOMに挿入されることです。ライフサイクル中に1回だけ起きます。
マウントは「初回レンダー + DOMへの挿入」の組み合わせです。
マウント = 初回レンダー + DOMへの挿入
コンポーネントがページに表示されるとき、Reactは次の順序で処理します。
- コンポーネント関数を呼ぶ(= 初回レンダー)
- 戻り値のJSXをDOMに挿入(= マウント完了)
useEffectのコールバックを実行(マウント後)
マウント = 画面リロード?
学習者マウントって、ページを再読み込みしたときのことでしょ?
これはよくある誤解です。画面リロードでマウントは起きますが、マウントは画面リロードだけで起きるものではありません。
集合の包含関係で整理すると、次のようになります。
レンダー ⊃ マウント ⊃ 画面リロード
| 用語 | 範囲 |
|---|---|
| レンダー | マウント + 再レンダーを含むすべて |
| マウント | 画面リロード + それ以外のマウントを含む |
| 画面リロード | マウントが起きる場面の1つにすぎない |
マウントが起きる場面
画面リロードは、アプリ全体をゼロから作り直すため全コンポーネントがマウントされます。しかしマウントはそれだけではありません。
function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(!show)}>toggle</button>
{show && <Child />}
</>
);
}この例では、ボタンを押して show が true になるたびに <Child /> がDOMに追加され、マウントが起きます。false になればアンマウントされ、再び true になれば新しいインスタンスとして再びマウントされます。
ページを再読み込みしなくても、以下の場面でマウントは発生します。
- 条件分岐で表示されたとき —
{show && <Component />} - ルート遷移で新しいページに移動したとき — 遷移先のコンポーネントがマウントされる
keyが変わったとき — Reactが別のインスタンスとして作り直す
useEffectの依存配列との対応
学習者条件分岐で表示したコンポーネントも毎回マウントされるなら、useEffect(..., []) は何回も実行されるってこと?
先生そのとおり。[] は「マウント時に1回だけ」だけど、コンポーネントが消えて再び表示されればまた新しいマウントだから、そのたびに実行されるよ。
どのパターンでもマウント時は必ず実行されるのが共通ルールです。
| 依存配列 | マウント時 | 再レンダー時 |
|---|---|---|
[] | 実行される | 実行されない |
[a, b] | 実行される | a か b が変わった時だけ実行 |
| なし | 実行される | 毎回実行される |
useEffect(..., []) が「1回だけ」と言われるのは、再レンダーでは実行されず、マウント時だけ実行されるためです。そして画面リロードに限らず、条件分岐やルート遷移でコンポーネントが表示されるたびにマウントは起きるため、[] でも複数回実行されることがあります。
再レンダーとアンマウント

再レンダー — stateやpropsの変化をきっかけに、マウント後に繰り返されるレンダーです。DOMへの挿入は最初の1回だけで、再レンダーではReactが差分だけを更新します。
アンマウント — コンポーネントが画面から取り除かれることです。条件分岐({show && <Component />})やルート遷移などで発生します。アンマウント時に useEffect のクリーンアップ関数が実行されます。
全体の流れ
コードで確認する
function Counter() {
const [count, setCount] = useState(0);
// レンダーのたびにここが実行される(初回 + 再レンダー)
console.log('rendered');
useEffect(() => {
// マウント時に1回だけ実行される
console.log('mounted');
return () => {
// アンマウント時に実行される
console.log('unmounted');
};
}, []);
return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
}ボタンを3回押したときのコンソール出力:
rendered ← 初回レンダー(マウント時)
mounted ← マウント完了後
rendered ← 再レンダー(1回目)
rendered ← 再レンダー(2回目)
rendered ← 再レンダー(3回目)
rendered は計4回(初回 + 3回)、mounted は1回だけです。コンポーネントが画面から消えるとき(アンマウント)に unmounted が出力されます。
useEffectとの関係
この違いが useEffect の依存配列と直接つながります。
// 依存配列なし → 毎レンダー後に実行(再レンダーのたびにも走る)
useEffect(() => {
console.log('every render');
});
// 空配列 → マウント時に1回だけ実行
useEffect(() => {
console.log('mount only');
}, []);「依存配列なし」と「空配列 []」は見た目が似ていますが、前者は毎レンダー後に実行され、後者はマウント時のみです。この違いはレンダーとマウントの概念を理解していれば自然に納得できます。
詳しくは「useEffect — 副作用と外部同期」で解説しています。
まとめ
- レンダー — コンポーネント関数の実行。stateやpropsの変化のたびに何度でも起きる。
- マウント — 初回レンダー + DOMへの挿入。ライフサイクル中に1回だけ。
- 再レンダー — 2回目以降のレンダー。DOMは差分だけ更新される。
- アンマウント — コンポーネントがDOMから取り除かれるとき。
useEffect(..., []) が「マウント時のみ」と言われるのは、空配列だと何にも反応しないため最初の1回しか実行されないからです。レンダーとマウントの違いを押さえると、フックの動作が一気にわかりやすくなります。
参考
- Render and Commit — React公式 — レンダーからDOMへの反映までの3ステップ
- Lifecycle of Reactive Effects — React公式 — Effectの開始・停止サイクルと依存配列の仕組み
- useEffect — React公式リファレンス — useEffectのAPI仕様・依存配列の挙動
