仮想DOMとReconciliation:Reactが「魔法」のように見える裏側の泥臭い真実
こんにちは。現場でReactを触っていると、「なぜReactはこんなに速いのか?」とふと疑問に思うことはないだろうか。
多くのチュートリアルでは「仮想DOMが効率的だから」と一言で片付けられるけれど、中級以上のエンジニアなら、その「効率的」の正体をもう少し解像度高く理解しておく必要がある。今日は、ReactがブラウザのDOMをいかにして「最小限」で書き換えているのか、その舞台裏にあるReconciliation(調整)とFiberアーキテクチャの泥臭い仕組みについて深掘りしていこう。
—
1. なぜ「直接DOMを触る」のは悪なのか
まず大前提だ。ブラウザにとって、DOMツリーの更新は極めてコストが高い操作だ。JavaScriptで`document.getElementById().innerHTML = …`を連発すれば、そのたびにブラウザはリフロー(レイアウト計算)やリペイントを走り回ることになる。
Reactの仮想DOM(Virtual DOM)は、この「重たいDOM操作」を、JavaScriptのオブジェクトという「軽量なメモリ上の表現」に置き換えたものだ。
1. 状態(State)が変わる。
2. Reactはメモリ上で新しい仮想DOMツリーを構築する。
3. 古いツリーと比較し、「差分(Diff)」だけを抽出する。
4. その差分だけを実DOMにパッチとして適用する。
この「3」のステップこそがReconciliationの核心だ。
2. Fiberアーキテクチャ:中断可能な「計算」の正体
かつてのReact(Stack reconciler)は、差分計算を一度始めたら止められない「同期的な再帰処理」だった。これが肥大化したコンポーネントツリーでフリーズを引き起こしていたんだ。
そこで登場したのがFiberだ。Fiberは、ツリーの更新作業を「小さなタスクの断片」に分割する。ブラウザのメインスレッドが空いた瞬間に少しずつ処理を進め、必要なら「もっと優先度の高い入力操作」に割り込みを許す。
この仕組みがあるからこそ、Reactは長時間かかる計算中でもユーザーの入力を阻害しない、「滑らかな体験」を提供できているんだ。
3. 実務で差がつく「差分検出」のヒント
Reactは差分計算を高速化するために、いくつかのヒューリスティック(経験則)を使っている。特に意識すべきは「リストのキー(`key` prop)」だ。
例えば、配列をレンダリングする際、`key`にインデックスを使うのは最悪のアンチパターンだ。要素の順序が変わった瞬間にReactは混乱し、全ての要素を再レンダリングすることになる。
現場で使える「差分を最小化する」コード例
次のコードは、リストの更新をReactがどう効率的に認識するかを示した最適化の例だ。
import React, { useState } from ‘react’;
// 実務的なポイント: keyには必ず一意で不変なIDを使う。
// インデックスは順序が変わるとバグの温床になる。
const UserList = ({ users }) => {
return (
-
{users.map((user) => (
- {user.name}
))}
);
};
export default function App() {
const [users, setUsers] = useState([
{ id: ‘a1’, name: ‘Alice’ },
{ id: ‘b2’, name: ‘Bob’ },
]);
const shuffle = () => {
// Reactはkeyを見て「あ、AliceとBobの場所が入れ替わっただけだな」と認識する。
// その結果、DOM要素の入れ替えのみが行われ、DOMの再構築は発生しない。
setUsers([…users].reverse());
};
return (
);
}
4. シニアからのアドバイス:計算を「サボる」技術
Reconciliationの仕組みを理解すると、次に考えるべきは「いかにReactの再計算を走らせないか」という技術だ。
- `React.memo`: Propsが同じなら再レンダリングをスキップする。ただし、安易に使うと逆に比較コストが増えることもあるので注意が必要だ。
- `useMemo` / `useCallback`: 重い計算結果や関数インスタンスの参照を保持する。これも「必要になったら」使うのが鉄則だ。
現場で一番恐ろしいのは、「何となくパフォーマンスが心配だから」という理由で全てのコンポーネントを`memo`で囲むことだ。それはエンジニアによる「過剰な最適化」であり、可読性を下げるだけのノイズでしかない。
「ボトルネックを見つけてから最適化する」。これが、Reconciliationを理解したエンジニアが守るべき最も重要な鉄則だ。
まとめ:魔法を「納得」に変えろ
Reactが裏側で何をしているかを知ることは、単なる教養ではない。バグが出たときに「なぜここで再レンダリングが走ったのか?」という問いに対して、ログを追う前に頭の中でコードの実行経路をシミュレートできるようになる。
仮想DOMは魔法じゃない。極めて論理的で、泥臭い最適化の塊だ。この仕組みを理解した君なら、もう「なんとなく動いているコード」からは卒業できるはずだ。
次は、ブラウザのプロファイラを使って、実際に自分の書いたコンポーネントがどうレンダリングされているか計測してみよう。それが、シニアへの登竜門だ。

コメント