Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
ReactがFiberツリーを比較して更新・挿入・削除を決定する方法。
リコンシリエーションは、stateやpropsが変更されたときにUIを効率的に更新するためのReactのアルゴリズムです。DOMツリー全体を再レンダリングする代わりに、Reactは前の仮想DOMツリーと新たにレンダリングされたツリーを比較し、必要な最小限の操作数を計算します。O(n³)ではなくO(n)時間でこれを行うために2つの主要なヒューリスティックを使用します。
Reactは次のことを前提とします:(1) 異なる型の要素は完全に異なるツリーを生成する — そのためReactは古いサブツリーをアンマウントして新しいものをマウントします。(2) 開発者はkey propを使用してレンダリングをまたいだ安定したIDをヒントとして提供できます。
2つの要素が同じ型(例:両方とも<div>)の場合、Reactは既存のDOMノードを保持し、変更された属性・propsのみを更新します。これにより不必要なDOMノードの破棄と再作成を避けられます。
型が変わった場合(例:<div>が<span>になる)、Reactは古いコンポーネントツリー全体をアンマウントし(すべてのクリーンアップを実行)、新しいツリーを新鮮な状態でマウントします。stateは失われます。
childrenのリストに対して、Reactはkeyで古いアイテムと新しいアイテムをマッチングします。keyなしでは、Reactは位置を使用します — アイテムが並べ替えられると不要なアンマウントを引き起こす可能性があります。keyによりReactは既存のDOMノードを効率的に移動できます。
Reactが両ツリーを走査するとき、「エフェクトリスト」を構築します — 作業(更新・挿入・削除)を持つFiberのリンクリストです。コミットフェーズはこのリストを走査して実際のDOMに変更を適用します。
Reactのリコンシリエーションエンジンにおける作業の単位。各コンポーネントは型、props、state、および親・子・兄弟Fiberへのポインタを格納するFiberノードを持ちます。
リコンシリエーション中にReactが変更を適用する現在のFiberツリーのクローン。コミットフェーズが完了した後にのみ「current」に昇格されます。
リコンシリエーション中に構築され、コミットフェーズで走査される、DOM変更を保留中のFiberのフラットなリンクリスト。
ReactがFiberのpropsとcontextが変更されていないことを検出した場合、そのサブツリーのレンダリングを完全にスキップできます — 重要なパフォーマンス最適化です。
1// Without keys — position-based matching (bad for reordering)2// Old: [<A/>, <B/>, <C/>]3// New: [<B/>, <A/>, <C/>]4// React sees: position 0 changed (updates A→B), position 1 changed (updates B→A)5// Result: 2 updates + possible state loss67// With keys — identity-based matching (correct)8// Old: [<A key="a"/>, <B key="b"/>, <C key="c"/>]9// New: [<B key="b"/>, <A key="a"/>, <C key="c"/>]10// React sees: same keys, just reordered11// Result: 0 updates, 2 DOM moves — much more efficient
リコンシリエーションは、ReactのDeclarativeモデルを実用的にするものです。UIがどのように見えるべきかを記述すれば、Reactが必要な最小限のDOM変更を計算します。Fiberアーキテクチャによりこれは中断可能になっています — ReactはツリーのどのFiberノードでもリコンシリエーションを一時停止し、後で再開できます。これによりSuspenseやトランジションなどの並行機能が可能になっています。
You have a todo list where users can delete items from the middle. Each item has an input field showing its text. After deleting the 2nd item, the 3rd item's input shows the 2nd item's text.
Using `index` as the key means when item 2 is deleted, React thinks item 3 IS item 2 (same key=2). It reuses the old component instance (with stale state) instead of destroying item 2 and moving item 3.
Use a stable unique ID (e.g., `todo.id`) as the key. Now React correctly identifies which component was removed and which should be kept. The reconciliation algorithm can match by identity instead of position.
Takeaway: The reconciliation algorithm's O(n) shortcut relies entirely on keys for list matching. Using array index as key defeats this optimization and introduces state bugs whenever order changes.
You have a conditional render: `isAdmin ? <AdminPanel /> : <UserPanel />`. Switching between admin and user views causes a full re-mount, destroying all form state.
React's reconciliation sees a different component TYPE at the same position. Its heuristic: 'different type = completely different tree'. It destroys the old subtree and builds a new one from scratch — losing all internal state.
If both panels share a similar structure, use the same component with conditional rendering inside. Or use `key` to explicitly control when a component should re-mount vs update. Understanding that React compares types first, then props, helps you design state-preserving UIs.
Takeaway: React's reconciliation compares elements top-down: type first, then key, then props. A type change always triggers a full unmount/remount of the entire subtree — this is by design, not a bug.