How React Works Internally

Most people use React without understanding what happens behind the scenes. That is fine for small projects, but understanding React's internals helps you write faster apps and debug problems that otherwise feel mysterious. This topic explains what happens from the moment you write a component to the moment users see it on screen.

The Browser DOM: The Problem React Solves

The browser renders pages using the Document Object Model, or DOM. The DOM is a tree of all the HTML elements on the page. Changing DOM nodes directly is slow — the browser recalculates layout and repaints the screen every time something changes.

Imagine a large spreadsheet. Every time you change one cell, the entire spreadsheet recalculates and redraws. That is exactly what browsers do with the DOM. React's job is to make those updates fast.

The Virtual DOM

React keeps a lightweight copy of the real DOM called the Virtual DOM. It lives in JavaScript memory, not in the browser.

How the Virtual DOM works — step by step

User interaction or state change
        |
        v
React creates a NEW Virtual DOM tree
        |
        v
React compares new tree with OLD Virtual DOM tree
  (This step is called "Diffing")
        |
        v
React finds only the CHANGED parts
        |
        v
React updates ONLY those parts in the real DOM
  (This step is called "Reconciliation")
        |
        v
Browser repaints only the changed area

Think of it like an editor reviewing a document. Instead of rewriting the whole document every time you fix a typo, the editor finds the one word that changed and corrects only that word.

JSX is Not HTML

When you write JSX in a React component, the browser cannot read it directly. A tool called Babel transforms your JSX into plain JavaScript React.createElement() calls before the browser ever sees it.

What you write

const element = <h1>Hello World</h1>;

What Babel turns it into

const element = React.createElement("h1", null, "Hello World");

React.createElement() creates a plain JavaScript object that describes what the element should look like. This object becomes a node in the Virtual DOM tree.

The React Fiber Architecture

React 16 introduced an internal engine called Fiber. Before Fiber, React had to finish all rendering work in one go. If a complex update took too long, the page would freeze.

Fiber broke rendering into small chunks of work that can be paused, prioritized, and resumed. Think of it as a smart task scheduler.

Fiber Priority System – like a hospital triage desk

HIGH PRIORITY (must process immediately)
  └── User clicks a button
  └── User types in an input box

NORMAL PRIORITY (process soon)
  └── Data loaded from an API
  └── Animation frames

LOW PRIORITY (process when free)
  └── Pre-loading off-screen content
  └── Background data sync

This is why React apps feel responsive even when complex updates happen in the background.

Reconciliation: How React Decides What Changed

When state or props change, React re-renders the component and produces a new Virtual DOM tree. It then compares this tree with the previous one using a process called reconciliation.

Two key rules React follows during reconciliation

Rule 1: Elements of different types get destroyed and rebuilt
// Before
<div>Hello</div>

// After
<p>Hello</p>

// React destroys the div and creates a fresh p element
Rule 2: Elements of the same type get updated in place
// Before
<button className="blue">Click</button>

// After
<button className="red">Click</button>

// React only updates the className, not the whole element

Why Keys Matter in Lists

When React renders a list of items, it needs a way to identify each item uniquely across renders. Without keys, React re-renders every list item even when only one changed.

// BAD – no keys, React cannot track items
{items.map(item => <li>{item.name}</li>)}

// GOOD – keys let React track each item
{items.map(item => <li key={item.id}>{item.name}</li>)}

Think of keys like student roll numbers. A teacher marks attendance faster with roll numbers than with names alone.

The React Render Cycle

Every component in React goes through a predictable cycle:

RENDER PHASE
  React calls your component function
  React builds the Virtual DOM tree
  (No side effects happen here)

COMMIT PHASE
  React updates the real DOM
  React runs useEffect callbacks
  (Side effects happen here)

The render phase can happen multiple times before committing. The commit phase happens only once per update cycle.

What Triggers a Re-render

React re-renders a component when any of these things happen:

  • The component's state changes via useState or useReducer
  • A prop passed to the component changes
  • The component's parent re-renders
  • A context value the component reads changes

React does not re-render a component just because time passes. A re-render always has a cause.

React Root: Where Everything Starts

Every React app attaches to one real DOM element — usually a div with the id of root.

// index.html
<div id="root"></div>

// main.jsx
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")).render(<App />);

React takes over that div completely and manages everything inside it.

Summary

React keeps a Virtual DOM in memory and compares it with the previous version every time something changes. It updates only the parts that actually changed in the real browser DOM. The Fiber engine makes this process smart and responsive by breaking work into prioritized chunks. JSX is converted to JavaScript by Babel before the browser runs it. Understanding these mechanics helps you write React code that performs well and behaves predictably.

Leave a Comment

Your email address will not be published. Required fields are marked *