Architecture Maps

React Internals

Interactive architecture map of React — Facebook's open-source UI library. Covering the Virtual DOM, Fiber reconciler with priority lanes, hooks system, concurrent features (Suspense, transitions), React Server Components, the synthetic event system, the React Compiler (React Forget), and the build tooling ecosystem.

Open Source (MIT) Since 2013 JavaScript / Flow ~230K GitHub Stars Most Used UI Library
01

System Overview

React is a declarative, component-based JavaScript library for building user interfaces. Created at Facebook in 2013, it pioneered the virtual DOM diffing approach and has since evolved into a sophisticated rendering system with concurrent capabilities, server-side rendering, and an automatic optimizing compiler.

230K+
GitHub Stars
~25M
Weekly npm Downloads
19
Major Versions
1700+
Contributors
Interactive Architecture Diagram — Click nodes for details
Virtual DOM
Fiber Reconciler
Hooks System
Concurrent Features
Server Components
Event System
Ecosystem
Compiler
02

Virtual DOM & Elements

React's core abstraction is the virtual DOM — a lightweight JavaScript representation of the actual DOM. When state changes, React builds a new virtual DOM tree, diffs it against the previous one, and applies only the minimal set of mutations needed to bring the real DOM up to date.

React Element Lifecycle
JSX
Declarative markup
createElement()
React element objects
Fiber Tree
Work-in-progress tree
Reconciliation
Diff & commit
Host DOM
Browser mutations

React Elements

Plain JavaScript objects with a type, key, ref, and props. JSX compiles to React.createElement() calls (or the new JSX transform's jsx()). Elements are immutable descriptions of what the UI should look like at a point in time.

Virtual DOM

JSX Transform

Since React 17, the new JSX transform automatically imports jsx from react/jsx-runtime, eliminating the need for import React. Babel or SWC compile JSX into function calls that create element descriptor objects.

Virtual DOM

Component Model

Components are functions (or classes) that accept props and return React elements. Function components are the primary model since React 16.8 (hooks). They compose into a tree that mirrors the UI hierarchy and can be lazy-loaded with React.lazy().

Virtual DOM

Keys & Reconciliation Hints

Keys help React identify which items in a list have changed, been added, or removed. Without stable keys, React falls back to index-based diffing which can cause subtle state bugs. Keys guide the reconciler's matching heuristic during tree diffing.

Virtual DOM
Why Virtual DOM?

Direct DOM manipulation is expensive — layout, paint, and composite phases are slow. By batching changes into a virtual representation and computing the minimal diff, React avoids unnecessary reflows. The virtual DOM also enables cross-platform rendering: the same component tree can target DOM, native mobile (React Native), canvas, or even terminal UIs.

03

Fiber Reconciler

Fiber is React's reconciliation engine, rewritten from scratch for React 16 (2017). Unlike the old stack reconciler which processed the entire tree synchronously, Fiber breaks rendering work into incremental units that can be paused, aborted, and resumed — enabling concurrent rendering and priority-based scheduling.

Fiber Node Structure

Each Fiber node is a JavaScript object representing a unit of work. It holds the component type, pending props, state, effect list, and pointers to form a linked tree: child, sibling, and return (parent). This linked structure allows traversal without recursion, enabling interruptible rendering.

Field Purpose Details
tag Fiber type identifier FunctionComponent, ClassComponent, HostComponent, SuspenseComponent, etc.
stateNode Underlying instance DOM node for host components, class instance for class components, null for functions
memoizedState Hook linked list Head of the linked list of hook state objects for function components
lanes Priority bitmask 32-bit bitmask indicating which priority lanes this fiber has pending work in
flags Side effects Placement, Update, Deletion, Snapshot, Passive (useEffect), Layout (useLayoutEffect)
alternate Double-buffering Points to the other version of this fiber (current vs. work-in-progress)

Work Loop

The core scheduling loop calls performUnitOfWork() in a while-loop, processing one fiber at a time. Each iteration calls beginWork() (render phase, going down) and completeWork() (going up). The loop checks shouldYield() to pause for higher-priority work or browser frames.

Fiber

Priority Lanes

React 18 uses a 32-bit lane model for scheduling. Each lane represents a priority level: SyncLane (user input), DefaultLane (normal updates), TransitionLane (startTransition), IdleLane (background). Multiple updates can be batched into the same lane.

Fiber

Double Buffering

React maintains two fiber trees: current (what is on screen) and workInProgress (being built). Each fiber has an alternate pointer to the other version. After committing, the work-in-progress tree becomes the current tree. This avoids visual tearing.

Fiber

Commit Phase

After the render phase completes the entire work-in-progress tree, the commit phase runs synchronously in three sub-phases: beforeMutation (snapshot), mutation (DOM writes), and layout (useLayoutEffect). This phase cannot be interrupted.

Fiber
Fiber vs. Stack Reconciler

The old stack reconciler (React 15 and below) processed the component tree with recursive function calls, making it impossible to pause mid-render. Fiber replaced this with an iterative linked-list traversal where each "unit of work" is a single fiber node. This unlocked concurrent rendering, Suspense, and time-sliced updates.

04

Hooks System

Introduced in React 16.8, hooks let function components manage state, side effects, context, refs, and more without classes. Under the hood, hooks are stored as a linked list on each fiber's memoizedState field, with a dispatcher that swaps between mount and update implementations.

Hook Storage Model
Fiber Node
memoizedState
Hook 1
useState
Hook 2
useEffect
Hook 3
useMemo
null
end of list

Dispatcher

React's internal ReactCurrentDispatcher swaps the hook implementation based on lifecycle phase. During mount, hooks use mountState, mountEffect, etc. During updates, they use updateState, updateEffect. This is why hooks must be called in the same order every render.

Hooks

useState / useReducer

Both use the same underlying queue mechanism. State updates are enqueued as objects with an action (value or reducer function) and a lane priority. The queue is processed during the render phase to compute the new state, with bailout optimization if the result is identical.

Hooks

useEffect / useLayoutEffect

useEffect schedules passive effects that run asynchronously after paint. useLayoutEffect runs synchronously during the commit phase's layout sub-phase, before the browser paints. Both compare dependency arrays to skip unnecessary re-runs. Cleanup functions run before the next effect.

Hooks

useMemo / useCallback

Memoization hooks that cache computed values (useMemo) or function references (useCallback) between renders. They compare dependency arrays and return the cached value if deps are unchanged. The React Compiler aims to make these unnecessary by auto-memoizing.

Hooks

useRef

Creates a mutable ref object ({ current: initialValue }) that persists across renders without triggering re-renders when mutated. Used for DOM access, storing previous values, and holding mutable instance-like data in function components.

Hooks

useContext

Subscribes a component to a React context. When the context value changes, all consuming components re-render. The context value is read from the nearest Provider up the fiber tree. Unlike other hooks, useContext doesn't have a dependency array — it always triggers on context change.

Hooks
Rules of Hooks

Hooks must be called at the top level of a function component (not inside conditions, loops, or nested functions) and only from React function components or custom hooks. This is because React identifies each hook by its call order — the linked list must be traversed in the same sequence every render. The eslint-plugin-react-hooks enforces these rules statically.

05

Concurrent Features

React 18 introduced concurrent rendering — the ability to prepare multiple versions of the UI simultaneously. Unlike synchronous rendering, concurrent mode lets React interrupt, prioritize, and discard renders to keep the app responsive during expensive updates.

startTransition

Marks a state update as non-urgent (a "transition"). React will render the transition in the background and keep the current UI responsive. If a higher-priority update arrives (e.g., user typing), React can interrupt and discard the in-progress transition render. useTransition also provides an isPending flag.

Concurrent

useDeferredValue

Defers updating a value until after more urgent renders complete. Conceptually similar to debouncing, but integrated into React's scheduler. The old value stays on screen while the new one renders in the background. Useful for expensive derived computations like search filtering.

Concurrent

Suspense

A component that catches thrown promises from its children and shows a fallback UI until they resolve. Originally for code splitting (React.lazy), now supports data fetching (via framework integrations), and streaming SSR. Multiple Suspense boundaries can nest to create progressive loading states.

Concurrent

Automatic Batching

React 18 automatically batches all state updates into a single re-render, even inside promises, timeouts, and event handlers. Previously, only React event handlers were batched. This reduces unnecessary renders and improves performance without any code changes.

Concurrent

useOptimistic (React 19)

Shows an optimistic state value during async operations. Takes the current state and an update function; immediately applies the optimistic update while the actual mutation is in flight. Reverts automatically if the mutation fails. Designed for form actions and data mutations.

Concurrent

use() Hook (React 19)

A new hook that can read the value of a Promise or Context resource. Unlike other hooks, use() can be called conditionally. When passed a Promise, it integrates with Suspense boundaries. This unifies the data-fetching pattern within React's rendering model.

Concurrent
Concurrent Rendering Model

Concurrent React doesn't use threads — it uses cooperative scheduling on the main thread. The work loop yields back to the browser between fiber units using shouldYield() (backed by MessageChannel or requestIdleCallback). This means React rendering never blocks user input for more than ~5ms at a time, even for complex component trees.

06

React Server Components

React Server Components (RSC) enable components that run exclusively on the server, sending only their rendered output to the client as a serialized payload. This eliminates the need to ship their JavaScript to the browser, reducing bundle size while allowing direct server-side data access.

RSC Request Flow
Server Component
async, server-only
RSC Payload
serialized React tree
Streaming SSR
HTML + flight data
Client Hydration
attach interactivity

Server Components

Components that render only on the server. They can be async, directly access databases, file systems, and APIs without exposing credentials. Their code is never shipped to the client bundle. They cannot use hooks, event handlers, or browser APIs. Marked by default (no directive needed).

RSC

"use client" Directive

The "use client" directive at the top of a file marks the server/client boundary. Components in that file (and its imports) become Client Components — they run on both server (SSR) and client. They can use hooks, event handlers, and browser APIs. This is the interactivity entry point.

RSC

RSC Payload (Flight)

Server Components serialize their output into a streaming protocol called "Flight" — a line-delimited format of React element references, serialized props, and client component module references. The client-side React runtime reconstructs the component tree from this payload without needing the server component code.

RSC

Streaming SSR

React 18's renderToPipeableStream() sends HTML progressively as Server Components resolve. Suspense boundaries define streaming chunks — content above a boundary streams immediately, while pending sections show fallbacks. When they resolve, React injects the HTML inline with a script to swap it in.

RSC

Server Actions

Functions marked with "use server" that run exclusively on the server but can be called from Client Components as form actions or event handlers. React serializes the arguments, sends them as a POST request, and handles the response — enabling zero-API-route data mutations.

RSC

Selective Hydration

React 18 can hydrate the page in priority order rather than all-at-once. Suspense boundaries define hydration chunks. If a user clicks on a not-yet-hydrated section, React prioritizes hydrating that section first. This dramatically improves Time to Interactive on large pages.

RSC
Server/Client Boundary

The boundary between Server and Client Components is a serialization boundary. Props passed from Server to Client Components must be serializable (JSON-compatible: strings, numbers, booleans, arrays, plain objects, Date, Map, Set, FormData, and certain React types like elements and lazy components). Functions, class instances, and symbols cannot cross this boundary (except Server Actions via "use server").

07

Event System

React implements its own event system on top of native browser events. Synthetic events provide a cross-browser consistent interface, while event delegation at the root container keeps listener count low and integrates cleanly with React's rendering lifecycle.

Synthetic Events

React wraps native browser events in SyntheticEvent objects that normalize cross-browser differences (event properties, bubbling behavior, etc.). Synthetic events are pooled for performance — though pooling was removed in React 17. They expose the same interface as native events.

Events

Event Delegation

Since React 17, all events are delegated to the root container element (not document as before). A single listener per event type captures all events and dispatches them through React's fiber tree. This enables multiple React roots on the same page and better micro-frontend compatibility.

Events

Event Priorities

React assigns lane priorities based on event type. Discrete events (click, keydown) get SyncLane (highest priority). Continuous events (scroll, mousemove) get lower priority. This ensures user input is always processed immediately while scroll handlers can be deferred.

Events

Event Plugins

Internally, React's event system uses a plugin architecture: SimpleEventPlugin, EnterLeaveEventPlugin, ChangeEventPlugin, SelectEventPlugin, and BeforeInputEventPlugin. Each plugin knows how to extract its events from native browser events and map them to React props.

Events
React 17 Event System Changes

React 17 moved event delegation from document to the root container, aligning event timing with the native capture/bubble phases. This fixed long-standing issues with event ordering when multiple React trees or third-party libraries are on the same page. It also dropped event pooling, since modern browsers handle object allocation efficiently.

08

React Compiler (React Forget)

The React Compiler (originally codenamed "React Forget") is an automatic optimizing compiler that analyzes your React code at build time and inserts memoization automatically. It understands React's rules (pure rendering, hooks rules) and generates equivalent code with optimal useMemo, useCallback, and React.memo applied.

Compiler Pipeline
Source Code
Your components
AST Analysis
Babel plugin
React IR
Intermediate repr.
Optimization
Auto-memoize
Output JS
Optimized code

Automatic Memoization

The compiler analyzes data flow in components and automatically wraps values, callbacks, and JSX in memoization guards. It can often do better than manual memoization because it operates on the full dependency graph of your component at the expression level, not just at the hook boundary.

Compiler

React IR

The compiler transforms JavaScript AST into an intermediate representation that models React-specific semantics: component boundaries, hook dependencies, effect scopes, and render-vs-effect code. This IR enables optimizations that a generic JavaScript compiler could not infer.

Compiler

Babel Plugin Integration

Ships as a Babel plugin (babel-plugin-react-compiler) that runs during your build. It also has experimental support as an SWC plugin for faster build times. The compiler only transforms function components and hooks — it leaves other JavaScript untouched.

Compiler

Strict Mode Compatibility

The compiler relies on React's rules: components must be pure functions of their props/state, hooks must follow the rules of hooks, and side effects must be in effects. Code that violates these rules may not be optimizable. The compiler can detect and skip non-conforming code with validation diagnostics.

Compiler
End of Manual Memoization

The React Compiler's goal is to make useMemo, useCallback, and React.memo unnecessary for most applications. The compiler can memoize at a finer granularity than developers typically do manually, often achieving better performance. Instagram has been running the compiler in production since 2024, reporting significant rendering performance improvements.

09

Build Tooling & Ecosystem

React's minimal core (just the component model and reconciler) is surrounded by a rich ecosystem of frameworks, build tools, and routing solutions. The React team now recommends using a framework for new projects rather than bare React with a custom setup.

Next.js

The most popular React framework. Provides file-based routing, static generation (SSG), server-side rendering (SSR), incremental static regeneration (ISR), API routes, middleware, and is the primary adopter of React Server Components. Used by Vercel, deployed globally on their edge network.

Ecosystem

React Router / Remix

React Router is the most-used client-side router. Remix (now merged with React Router v7) adds loader/action data patterns, nested routing with parallel data fetching, progressive enhancement, and server rendering. It runs on any JS runtime (Node, Deno, Cloudflare Workers).

Ecosystem

Vite

The modern build tool for React development. Uses native ES modules for instant dev server startup and Rollup for production builds. React Fast Refresh is provided via @vitejs/plugin-react (Babel) or @vitejs/plugin-react-swc (SWC, 20x faster transforms). Replaced Create React App as the community standard.

Ecosystem

React Native

The cross-platform mobile framework using React. Renders to native iOS/Android views instead of DOM. Uses the same Fiber reconciler with a different host config. The New Architecture (Fabric renderer + TurboModules + JSI) provides synchronous native calls and concurrent rendering support.

Ecosystem

Expo

The managed platform for React Native. Provides a development client, over-the-air updates (EAS Update), build service (EAS Build), file-based routing (Expo Router), universal React for web and mobile, and a curated set of native module bindings with consistent APIs.

Ecosystem

React DevTools

Browser extension and standalone tool for inspecting the React component tree, profiling renders, viewing hooks state, examining Suspense boundaries, and debugging re-renders. The Profiler measures component render times and identifies unnecessary re-renders with flame graphs.

Ecosystem
10

State Management Patterns

React provides built-in state primitives (useState, useReducer, useContext), but complex applications often need additional patterns. The ecosystem offers solutions ranging from centralized stores to atomic state to server-cache synchronization — each addressing different trade-offs.

Library Pattern Key Concept
Redux / RTK Centralized store Single immutable state tree, dispatched actions, pure reducer functions. Redux Toolkit adds opinionated defaults with createSlice and RTK Query for data fetching.
Zustand Minimalist store Hook-based store with no providers or boilerplate. Uses external subscription with selector-based re-render optimization. ~1KB bundle.
Jotai Atomic state Bottom-up approach with primitive atoms. Derived atoms compose from other atoms. No selectors needed — components subscribe to exactly the atoms they read.
TanStack Query Server cache Manages server state (fetching, caching, synchronizing, background updates). Deduplicates requests, handles stale-while-revalidate, retry, pagination, and infinite scroll.
Recoil Graph-based Facebook's experimental atomic state with atoms and selectors forming a data-flow graph. Supports async selectors and atomFamily for parameterized state.
Valtio Proxy-based Mutate state directly with JavaScript Proxy tracking. React re-renders only components that access changed properties. Feels like MobX but with React hooks.
React 19 and Server State

With React Server Components and Server Actions in React 19, much of what was traditionally "client state management" can move to the server. Server Components fetch data directly, Server Actions handle mutations, and useOptimistic manages optimistic UI updates. For many applications, this eliminates the need for a separate client-side data fetching library entirely.

Key Concepts

Connections