How to Implement Reconciliation in React

This article explains how React’s reconciliation process works to efficiently update the User Interface (UI). You will learn the core concepts behind the virtual DOM, the heuristic diffing algorithm React uses, and the practical steps developers must take to ensure React reconciles components optimally.

What is Reconciliation?

Reconciliation is the process through which React updates the real DOM. When a component’s state or props change, React creates a new virtual DOM tree. Instead of rendering the entire UI from scratch, React compares this new virtual DOM tree with the previous one to identify what has changed. It then updates only the necessary parts of the real DOM, ensuring high performance.

The Diffing Algorithm

React implements reconciliation using a heuristic \(O(n)\) diffing algorithm. This algorithm is based on two key assumptions:

  1. Different Element Types: Two elements of different types will produce different trees.
  2. Keys for Dynamic Lists: The developer can hint which child elements may be stable across different renders using a key prop.

1. Elements of Different Types

Whenever the root elements of a subtree have different types (for example, changing a <div> to a <span>, or a <Counter> to a <Header>), React tears down the old tree and builds the new tree from scratch. Any state associated with the old components is completely destroyed.

2. DOM Elements of the Same Type

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the underlying DOM node, and only updates the changed attributes (such as className or style).

3. Component Elements of the Same Type

When a component updates, the instance stays the same so that state is maintained across renders. React updates the props of the underlying component instance to match the new element and triggers a re-render.

How to Implement Reconciliation Best Practices

As a developer, you do not write the core reconciliation algorithm yourself; React handles it automatically under the hood. However, you must write code that helps React’s algorithm make the most efficient decisions.

1. Use Stable, Unique Keys for Lists

When rendering lists of elements, React relies on the key prop to match children in the original tree with children in the subsequent tree.

// Correct implementation
<ul>
  {items.map(item => (
    <li key={item.id}>{item.text}</li>
  ))}
</ul>

2. Maintain Stable Component Structures

Avoid dynamically changing the element type if you want to preserve state. If you change a component wrapper from a div to a section, React will destroy the entire subtree and its state. Keep your component hierarchy stable wherever possible.

3. Prevent Unnecessary Re-renders

You can instruct React to skip the reconciliation process entirely for specific subtrees if their props have not changed.

import React, { memo } from 'react';

const MyComponent = memo(({ data }) => {
  return <div>{data.name}</div>;
});