Structure of the React Codebase
React is all around us, but more specifically it's a monorepo containing several packages. Here's a breakdown on the structure of the core React codebase, also covers the React Scheduler and Reconciler.

React Codebase Structure
The structure of the codebase has separation of concerns between the core logic, the reconciliation algorithm, and the platform-specific renderers.
Package Breakdown
packages/
This directory contains the source code for all React packages.
react: The core package. It contains the isomorphic APIs likeReact.createElement,React.Component,React.useState, etc. It is platform-agnostic.- Note: An "isomorphic API" (or universal API) means the code can run in multiple environments (Web, Mobile, VR) without modification. It defines how you describe a UI, while renderers handle how to draw it.
react-reconciler: This is the heart of React. It implements the "Fiber" architecture and the reconciliation algorithm. It manages the component tree, diffing, and state updates. It is used by renderers to implement custom rendering logic.scheduler: A package responsible for cooperative multitasking. It handles prioritizing tasks (like rendering updates) to ensure the main thread remains responsive.react-dom: The renderer for the DOM. It acts as the bridge betweenreact-reconcilerand the browser's DOM APIs.react-native-renderer: The renderer for React Native.shared: Contains utility functions and constants shared across multiple packages.
fixtures/
Contains small React applications used for testing and debugging.
scripts/
Contains scripts for building, testing, and managing the repository (e.g., release scripts, flow checks).
Architectural Layers
- Core (API):
reactpackage. What developers interact with. - Reconciler (Logic):
react-reconciler. Handles the "when" and "what" of updates. - Renderer (Platform):
react-dom,react-native-renderer. Handles the "where" (painting pixels, DOM nodes).
React Scheduler
The scheduler package is a standalone package in the React repository responsible for scheduling tasks. It implements a cooperative multitasking model.
JavaScript is single-threaded. If a long-running task (like rendering a large component tree) blocks the main thread, the browser becomes unresponsive to user input, animations stutter, and the app feels sluggish.
The Scheduler allows React to break long tasks into smaller chunks (time slicing) and yield control back to the browser periodically.
Key Concepts
Cooperative Multitasking
Instead of the browser deciding when to stop a task (preemptive), the task itself (React) cooperatively yields control back to the Scheduler. The Scheduler then decides whether to continue the task or yield to the browser to handle higher-priority events (like input or painting).
Time Slicing
The Scheduler allocates a "slice" of time (typically 5ms) for React to do work.
- React performs work.
- It periodically checks
Scheduler.shouldYield(). - If the time slice is expired, React pauses its work and yields.
- The Scheduler schedules a continuation callback to resume the work in the next available frame.
Priorities
The Scheduler assigns priorities to tasks to determine their execution order.
- ImmediatePriority: Must run synchronously (e.g., expired tasks).
- UserBlockingPriority: Result of user interaction (e.g., button click). Needs to run quickly (within ~250ms) to feel instant.
- NormalPriority: Default priority for state updates (e.g., data fetch response). (Target ~5s).
- LowPriority: Low priority work (e.g., logging). (Target ~10s).
- IdlePriority: Run only when the main thread is completely idle.
Implementation Details
- MessageChannel: The Scheduler primarily uses
MessageChannelto schedule tasks on the macro-task queue. This is preferred oversetTimeoutbecause it has less nesting clamping and runs earlier in the event loop. requestHostCallback: The internal mechanism to request the host (browser) to execute a callback.shouldYieldToHost: A function that checks if the current deadline has been exceeded or if there is high-priority input pending (usingnavigator.scheduling.isInputPendingif available).
Integration with React
The react-reconciler depends on the scheduler.
- When a state update occurs, React asks the Scheduler to schedule a callback.
- The Scheduler invokes the callback when appropriate based on priority.
- Inside the callback, React performs the "Render Phase".
- During the render loop, React checks
shouldYield()to see if it needs to pause.
React Reconciler and Fiber Architecture
The react-reconciler package is the core logic engine of React. It is responsible for computing changes in the UI component tree and applying them efficiently. Since React 16, this has been powered by the Fiber architecture.
What is Fiber?
Fiber is a reimplementation of the stack, specialized for React components. You can think of a single fiber as a virtual stack frame.
The primary goal of Fiber is to enable incremental rendering: the ability to split rendering work into chunks and spread it out over multiple frames.
Key Features
- Pause and Resume: React can pause work on a low-priority update to handle a high-priority event (like user input), and then resume where it left off.
- Prioritization: Different types of updates have different priorities (e.g., animation > user input > data fetching).
- Reuse: React can reuse previously completed work if it's still valid.
- Abort: React can throw away work if it's no longer needed.
The Structure of a Fiber
A Fiber is a JavaScript object that contains information about a component, its input, and its output. Key properties include:
type: The function or class associated with the fiber (e.g.,div,MyComponent).key: Unique identifier for the fiber, used for diffing lists.child,sibling,return: Pointers that form the fiber tree structure (a singly linked list traversal of the tree).pendingProps/memoizedProps: The props used to create the fiber vs the props used during the last render.memoizedState: The internal state of the fiber (e.g., hooks list).alternate: A link to the counterpart fiber in the "other" tree (see Double Buffering).
Double Buffering
React maintains two fiber trees at any given time:
- Current Tree: Represents what is currently displayed on the screen.
- Work-in-Progress (WIP) Tree: The tree React builds in the background during an update.
When React starts working on an update, it clones the current tree to create the workInProgress tree. It performs all logic and diffing on the WIP tree. Once the WIP tree is complete and committed to the DOM, it becomes the new current tree.
The Two Phases
The reconciliation process is divided into two phases:
1. Render Phase (Asynchronous, Interruptible)
- React traverses the fiber tree, calling component functions and diffing children.
- It calculates what changes need to be made (side effects).
- This phase is pure (no side effects visible to the user) and can be paused, aborted, or restarted.
- Result: A tree of fibers marked with "flags" (effects) describing operations like Placement, Update, or Deletion.
2. Commit Phase (Synchronous, Uninterruptible)
- React takes the finished WIP tree and applies the calculated changes to the host environment (e.g., the DOM).
- Lifecycle methods like
componentDidMountanduseEffectare triggered here. - This phase cannot be interrupted because it results in visible changes to the UI.
