LEARN REACT INTERNALS
Learn React Internals: How React Really Works
Goal: Deeply understand React’s internal architecture—Virtual DOM, Fiber reconciliation, hooks implementation, JSX compilation, event system, and concurrent rendering.
Why Learn React Internals?
Most React developers use React like a black box. They know useState updates state and triggers a re-render, but not how. Understanding React’s internals transforms you from a React user to a React master:
- Debug faster: When you understand the render cycle, you spot issues immediately
- Write performant code: Knowing Fiber helps you avoid unnecessary re-renders
- Ace interviews: “How does React work internally?” is a senior-level question
- Contribute to React: The React team welcomes informed contributors
- Build similar tools: Understanding the patterns lets you build your own libraries
Core Concept Analysis
The Big Picture: React’s Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ YOUR CODE │
│ │
│ const App = () => { │
│ const [count, setCount] = useState(0); │
│ return <button onClick={() => setCount(c => c+1)}>{count}</button>│
│ } │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ BABEL/COMPILER │
│ │
│ JSX → React.createElement() calls │
│ <button> → createElement('button', {onClick: ...}, count) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ REACT ELEMENT TREE │
│ (Virtual DOM) │
│ │
│ { type: 'button', props: { onClick: fn, children: 0 } } │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ FIBER TREE │
│ (Work Units) │
│ │
│ FiberNode { │
│ type: 'button', │
│ stateNode: <actual DOM node>, │
│ memoizedState: { hooks: [...] }, │
│ effectTag: UPDATE, │
│ ... │
│ } │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ RECONCILER │
│ │
│ 1. Render Phase (can be interrupted) │
│ - Build Work-in-Progress tree │
│ - Diff with current tree │
│ - Collect effects (DOM updates needed) │
│ │
│ 2. Commit Phase (synchronous) │
│ - Apply all DOM mutations │
│ - Run effects (useEffect, useLayoutEffect) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ ACTUAL DOM │
│ │
│ <button>0</button> │
└─────────────────────────────────────────────────────────────────────┘
Key Concepts Explained
1. JSX Compilation
JSX is syntactic sugar. Babel transforms it into function calls:
// You write:
<div className="container">
<h1>Hello</h1>
<p>World</p>
</div>
// Babel compiles to:
React.createElement('div', { className: 'container' },
React.createElement('h1', null, 'Hello'),
React.createElement('p', null, 'World')
);
// Which returns a React Element (plain object):
{
type: 'div',
props: {
className: 'container',
children: [
{ type: 'h1', props: { children: 'Hello' } },
{ type: 'p', props: { children: 'World' } }
]
}
}
New JSX Transform (React 17+): No longer requires import React because Babel auto-imports jsx from react/jsx-runtime.
2. Virtual DOM
The Virtual DOM is a JavaScript representation of the actual DOM. It’s a tree of plain objects (React Elements).
// Virtual DOM node (React Element)
const element = {
type: 'div', // Tag name or component function
props: { // Attributes + children
className: 'app',
children: [...]
},
key: null, // For reconciliation
ref: null // DOM reference
};
Why Virtual DOM?
- DOM operations are slow; JS operations are fast
- Batch multiple changes into single DOM update
- Enables diffing algorithm (only update what changed)
- Platform agnostic (same model for web, native, VR)
3. Fiber Architecture
Fiber is React’s reconciliation engine (since React 16). Each Fiber is a unit of work representing a component instance.
// Simplified Fiber Node structure
FiberNode = {
// Identity
type: Function | String, // Component function or tag name
key: String | null,
// Relationships (tree structure)
child: Fiber | null, // First child
sibling: Fiber | null, // Next sibling
return: Fiber | null, // Parent
// State
memoizedState: any, // Current state (hooks linked list)
memoizedProps: Object, // Current props
pendingProps: Object, // New props
// Effects
effectTag: number, // What to do (UPDATE, PLACEMENT, DELETION)
nextEffect: Fiber | null, // Next fiber with effects
// DOM
stateNode: DOMNode | null, // Actual DOM node
// Alternate (double buffering)
alternate: Fiber | null // Work-in-progress counterpart
}
Key Innovation: Fiber enables incremental rendering—work can be paused, resumed, or abandoned.
4. Reconciliation (Diffing Algorithm)
React’s diffing algorithm compares old and new Virtual DOM trees:
Two Key Heuristics:
- Different types → Replace entire subtree
- Same type → Update attributes, recurse on children
The Algorithm:
1. Compare root elements
- Different type? → Unmount old, mount new
- Same type? → Keep node, update props
2. Recurse on children
- Without keys: Compare by index (inefficient for lists)
- With keys: Match by key (efficient reordering)
3. Collect effects (what DOM operations are needed)
Why Keys Matter:
// Without keys - React compares by index
// Inserting at beginning re-renders ALL items
[A, B, C] → [Z, A, B, C] // React thinks: A→Z, B→A, C→B, +C
// With keys - React matches by identity
[A:a, B:b, C:c] → [Z:z, A:a, B:b, C:c] // React knows: just insert Z
5. Two-Phase Rendering
React renders in two distinct phases:
Render Phase (Interruptible):
- Build new Fiber tree (Work-in-Progress)
- Call component functions / render methods
- Diff with current tree
- NO side effects yet (no DOM changes)
- Can be paused, resumed, or discarded
Commit Phase (Synchronous):
- Apply all DOM mutations at once
- Run
useLayoutEffect(blocking) - Swap current ↔ WIP tree pointers
- Run
useEffect(non-blocking, after paint)
Time →
[---- Render Phase ----][-- Commit --][-- useEffect --]
↑
DOM Updated
(User sees change)
6. How Hooks Work Internally
Hooks are stored as a linked list on the Fiber node:
// Simplified hooks storage
fiber.memoizedState = {
// First hook (useState)
memoizedState: 0, // Current state value
queue: { pending: null }, // Update queue
next: {
// Second hook (useEffect)
memoizedState: {
create: () => {...}, // Effect callback
destroy: undefined, // Cleanup function
deps: [dep1, dep2] // Dependencies
},
next: {
// Third hook (useRef)
memoizedState: { current: null },
next: null
}
}
};
Why Order Matters (Rules of Hooks): React identifies hooks by their call order, not by name. The hook index must be consistent across renders:
// ❌ WRONG - conditional hook
if (condition) {
const [state, setState] = useState(0); // Index 0 sometimes
}
const [other, setOther] = useState(1); // Index 0 or 1?
// ✅ CORRECT - consistent order
const [state, setState] = useState(0); // Always index 0
const [other, setOther] = useState(1); // Always index 1
if (condition) {
// use state here
}
7. Synthetic Events
React wraps native browser events in SyntheticEvent objects:
// React doesn't attach handlers to each element
// Instead: one listener at the root (event delegation)
// Before React 17: document level
document.addEventListener('click', handler);
// React 17+: React root level
rootContainer.addEventListener('click', handler);
// When event fires:
1. Native event bubbles to root
2. React finds the target element
3. Creates SyntheticEvent (cross-browser wrapper)
4. Walks up fiber tree, calling matching handlers
Why Synthetic Events?
- Cross-browser consistency
- Performance (event delegation = fewer listeners)
- Event pooling (reuse event objects) - deprecated in React 17
- Integration with React’s update batching
8. Concurrent Rendering & Time Slicing
React 18 introduced concurrent features powered by the Scheduler:
Time Slicing: Break rendering into 5ms chunks, yield to browser between chunks.
Legacy Mode (blocking):
[=============== 100ms render ===============]
❌ Browser frozen, can't respond to input
Concurrent Mode (time-sliced):
[5ms][5ms][5ms][5ms]...[5ms]
↑ ↑ ↑
Browser can process input between chunks
Priority Levels:
- Immediate: User input (typing, clicking)
- User-blocking: Hover, scroll
- Normal: Data fetching results
- Low: Analytics
- Idle: Prefetching
Key APIs:
useTransition: Mark updates as non-urgentuseDeferredValue: Defer expensive re-rendersstartTransition: Lower priority for wrapped updates
Project List
The following 14 projects will teach you React internals from first principles, culminating in building your own React.
Project 1: Build Your Own createElement
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 1: Beginner
- Knowledge Area: JSX / Virtual DOM / React Elements
- Software or Tool: Node.js, Babel (optional)
- Main Book: Build Your Own React (pomb.us)
What you’ll build: A createElement function that transforms JSX-like syntax into a tree of plain JavaScript objects (Virtual DOM).
Why it teaches React internals: This is the entry point to React. Every JSX tag becomes a createElement call. Understanding this shows you that React Elements are just objects—nothing magical.
Core challenges you’ll face:
- Handling different element types → maps to components vs DOM elements
- Normalizing children → maps to text nodes, arrays, null
- Understanding the element structure → maps to type, props, key, ref
Resources for key challenges:
- Build Your Own React - Rodrigo Pombo’s excellent guide
- How Babel Transforms JSX
Key Concepts:
- React Elements: Plain objects describing what to render
- JSX Transformation: Babel’s role
- Children Normalization: Handling various child types
Difficulty: Beginner Time estimate: 2-3 days Prerequisites: JavaScript basics, understanding of trees
Real world outcome:
// Your createElement function
function createElement(type, props, ...children) {
return {
type,
props: {
...props,
children: children.map(child =>
typeof child === 'object' ? child : createTextElement(child)
)
}
};
}
function createTextElement(text) {
return {
type: 'TEXT_ELEMENT',
props: { nodeValue: text, children: [] }
};
}
// Usage (or via Babel JSX transform)
const element = createElement(
'div',
{ className: 'container' },
createElement('h1', null, 'Hello'),
createElement('p', null, 'World')
);
console.log(element);
// {
// type: 'div',
// props: {
// className: 'container',
// children: [
// { type: 'h1', props: { children: [...] } },
// { type: 'p', props: { children: [...] } }
// ]
// }
// }
Implementation Hints:
The key insight is that React Elements are just objects. Nothing more:
// A React Element is just:
{
type: 'div' | MyComponent, // String for DOM, function for components
props: {
// All attributes
className: 'container',
onClick: () => {},
// Children are also in props
children: [/* more elements */]
},
key: null, // For reconciliation
ref: null // For DOM access
}
Handle edge cases:
nullandundefinedchildren (skip them)- Primitive children (wrap in text element)
- Array children (flatten)
Learning milestones:
- Basic createElement works → You understand element structure
- Text nodes handled → You normalize children
- Nested elements work → You can build any tree
- Configure Babel to use your createElement → Full JSX support
Project 2: Build Your Own Renderer (DOM)
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: DOM Manipulation / Rendering
- Software or Tool: Browser, Node.js
- Main Book: Build Your Own React (pomb.us)
What you’ll build: A render function that takes a Virtual DOM tree and creates actual DOM nodes, appending them to a container.
Why it teaches React internals: This is ReactDOM’s core job—turning React Elements into real DOM. Understanding this shows you the Virtual DOM → Real DOM translation.
Core challenges you’ll face:
- Creating DOM elements from virtual nodes → maps to document.createElement
- Setting props/attributes → maps to attribute handling, event listeners
- Recursively rendering children → maps to tree traversal
- Handling text nodes → maps to createTextNode
Key Concepts:
- DOM APIs: createElement, createTextNode, appendChild
- Attribute Handling: Properties vs attributes
- Event Handling: addEventListener
Difficulty: Intermediate Time estimate: 3-4 days Prerequisites: Project 1, DOM API knowledge
Real world outcome:
function render(element, container) {
// Create DOM node
const dom =
element.type === 'TEXT_ELEMENT'
? document.createTextNode('')
: document.createElement(element.type);
// Set properties
Object.keys(element.props)
.filter(key => key !== 'children')
.forEach(name => {
if (name.startsWith('on')) {
const eventType = name.toLowerCase().substring(2);
dom.addEventListener(eventType, element.props[name]);
} else {
dom[name] = element.props[name];
}
});
// Render children recursively
element.props.children.forEach(child => render(child, dom));
// Append to container
container.appendChild(dom);
}
// Usage
const element = createElement(
'div',
{ className: 'app' },
createElement('h1', null, 'Hello React!'),
createElement('button', { onClick: () => alert('Clicked!') }, 'Click me')
);
render(element, document.getElementById('root'));
Implementation Hints:
Property handling has nuances:
// Some properties are different from attributes
if (name === 'className') {
dom.className = value;
} else if (name === 'style' && typeof value === 'object') {
Object.assign(dom.style, value);
} else if (name.startsWith('on')) {
dom.addEventListener(name.slice(2).toLowerCase(), value);
} else {
dom.setAttribute(name, value);
}
Learning milestones:
- Static elements render → Basic DOM creation works
- Props are set → Attributes and styles work
- Events work → onClick, onChange fire
- Children render → Nested structures work
Project 3: Implement the Diffing Algorithm
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Algorithms / Tree Comparison
- Software or Tool: Browser
- Main Book: React Reconciliation Docs
What you’ll build: A diffing algorithm that compares old and new Virtual DOM trees and generates minimal DOM operations.
Why it teaches React internals: This is the heart of React’s performance. Instead of replacing the entire DOM, React calculates the minimum changes needed.
Core challenges you’ll face:
- Comparing element types → maps to same type = update, different = replace
- Diffing props → maps to add, remove, update attributes
- Diffing children → maps to the key algorithm
- Generating patches → maps to describing DOM operations
Resources for key challenges:
- Reconciliation Documentation - Official algorithm explanation
- Virtual DOM Diffing
Key Concepts:
- Tree Diffing Heuristics: O(n) instead of O(n³)
- Keys for Children: Efficient list reconciliation
- Patch Objects: Describing changes
Difficulty: Advanced Time estimate: 1 week Prerequisites: Projects 1-2, algorithm basics
Real world outcome:
function diff(oldNode, newNode) {
// No new node → Remove
if (!newNode) {
return { type: 'REMOVE' };
}
// No old node → Add
if (!oldNode) {
return { type: 'ADD', newNode };
}
// Different types → Replace
if (oldNode.type !== newNode.type) {
return { type: 'REPLACE', newNode };
}
// Same type → Update props, diff children
if (typeof oldNode.type === 'string') {
const propPatches = diffProps(oldNode.props, newNode.props);
const childPatches = diffChildren(
oldNode.props.children,
newNode.props.children
);
return { type: 'UPDATE', propPatches, childPatches };
}
}
// Example usage
const oldTree = createElement('div', { className: 'old' },
createElement('p', null, 'Hello')
);
const newTree = createElement('div', { className: 'new' },
createElement('p', null, 'Hello'),
createElement('p', null, 'World') // Added
);
const patches = diff(oldTree, newTree);
// { type: 'UPDATE',
// propPatches: [{ className: 'old' → 'new' }],
// childPatches: [null, { type: 'ADD', ... }]
// }
Implementation Hints:
The key insight is React’s heuristics:
// Heuristic 1: Different types = completely different trees
// Don't try to match <div> children with <span> children
if (oldNode.type !== newNode.type) {
return { type: 'REPLACE', newNode };
}
// Heuristic 2: Keys identify children across renders
function diffChildren(oldChildren, newChildren) {
// Build map of old children by key
const oldKeyedChildren = {};
oldChildren.forEach((child, i) => {
const key = child.props?.key ?? i;
oldKeyedChildren[key] = { child, index: i };
});
// Match new children to old by key
return newChildren.map((newChild, i) => {
const key = newChild.props?.key ?? i;
const old = oldKeyedChildren[key];
if (old) {
return diff(old.child, newChild);
} else {
return { type: 'ADD', newNode: newChild };
}
});
}
Learning milestones:
- Type comparison works → Replace when types differ
- Prop diffing works → Minimal attribute updates
- Child diffing works → Handles additions/removals
- Keys work → Efficient list reordering
Project 4: Build Fiber-like Work Units
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Fiber Architecture / Incremental Rendering
- Software or Tool: Browser, requestIdleCallback
- Main Book: React Fiber Architecture (GitHub)
What you’ll build: A Fiber-like work loop that breaks rendering into units of work, allowing the browser to interrupt and handle user input.
Why it teaches React internals: This is React’s biggest architectural innovation since Virtual DOM. Fiber enables concurrent rendering by making work interruptible.
Core challenges you’ll face:
- Creating Fiber nodes → maps to work unit structure
- Building the work loop → maps to requestIdleCallback / scheduler
- Traversing the tree → maps to child, sibling, return pointers
- Committing work → maps to two-phase rendering
Resources for key challenges:
- React Fiber Architecture - Andrew Clark’s explanation
- Deep Dive into React Fiber
Key Concepts:
- Fiber Node Structure: type, props, state, effects
- Work Loop: Interruptible rendering
- Double Buffering: Current tree vs WIP tree
Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Projects 1-3
Real world outcome:
// Fiber node structure
function createFiber(element, parent) {
return {
type: element.type,
props: element.props,
parent,
child: null,
sibling: null,
alternate: null, // Link to current tree
effectTag: null, // UPDATE, PLACEMENT, DELETION
dom: null // Actual DOM node
};
}
// Work loop
let nextUnitOfWork = null;
let wipRoot = null; // Work-in-progress root
let currentRoot = null; // Current tree on screen
function workLoop(deadline) {
let shouldYield = false;
while (nextUnitOfWork && !shouldYield) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
shouldYield = deadline.timeRemaining() < 1; // Yield if < 1ms left
}
// If all work done, commit
if (!nextUnitOfWork && wipRoot) {
commitRoot();
}
requestIdleCallback(workLoop);
}
requestIdleCallback(workLoop);
// Process one fiber, return next
function performUnitOfWork(fiber) {
// 1. Create DOM if needed
if (!fiber.dom) {
fiber.dom = createDom(fiber);
}
// 2. Create fibers for children
const elements = fiber.props.children;
let prevSibling = null;
elements.forEach((element, index) => {
const newFiber = createFiber(element, fiber);
if (index === 0) {
fiber.child = newFiber;
} else {
prevSibling.sibling = newFiber;
}
prevSibling = newFiber;
});
// 3. Return next unit of work
// First try child, then sibling, then uncle
if (fiber.child) return fiber.child;
let nextFiber = fiber;
while (nextFiber) {
if (nextFiber.sibling) return nextFiber.sibling;
nextFiber = nextFiber.parent;
}
return null;
}
Implementation Hints:
Tree traversal order:
A Traversal: A → B → D → E → C → F
/ \
B C 1. Go to child if exists
/ \ \ 2. Else go to sibling
D E F 3. Else go to parent's sibling (uncle)
Double buffering:
// Two trees
currentRoot // What's on screen
wipRoot // What we're building
// On commit, swap them
function commitRoot() {
commitWork(wipRoot.child);
currentRoot = wipRoot;
wipRoot = null;
}
Learning milestones:
- Work loop runs → Fibers process over multiple frames
- Tree builds correctly → Child/sibling links work
- Can yield to browser → Animation doesn’t stutter
- Commit phase works → DOM updates atomically
Project 5: Implement useState Hook
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Hooks / State Management
- Software or Tool: Your mini-React
- Main Book: Under the Hood of React’s Hooks System
What you’ll build: A working useState hook that persists state across renders and triggers re-renders on updates.
Why it teaches React internals: Hooks seem magical but are surprisingly simple. They’re just arrays/linked lists stored on the Fiber node.
Core challenges you’ll face:
- Storing state on the fiber → maps to memoizedState
- Maintaining hook order → maps to Rules of Hooks
- Triggering re-renders → maps to update queues
- Handling multiple useState calls → maps to hook index
Resources for key challenges:
- How React Hooks Work Under the Hood
- Under the Hood of React’s Hooks
- Deep Dive: How Do React Hooks Really Work?
Key Concepts:
- Hook Storage: Linked list on fiber.memoizedState
- Closure Over State: How setState captures correct value
- Update Queue: Batching state updates
Difficulty: Advanced Time estimate: 1 week Prerequisites: Project 4 (Fiber)
Real world outcome:
let wipFiber = null;
let hookIndex = null;
function useState(initial) {
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
const hook = {
state: oldHook ? oldHook.state : initial,
queue: []
};
// Process pending state updates
const actions = oldHook ? oldHook.queue : [];
actions.forEach(action => {
hook.state = typeof action === 'function'
? action(hook.state)
: action;
});
const setState = action => {
hook.queue.push(action);
// Trigger re-render
wipRoot = {
dom: currentRoot.dom,
props: currentRoot.props,
alternate: currentRoot
};
nextUnitOfWork = wipRoot;
};
wipFiber.hooks.push(hook);
hookIndex++;
return [hook.state, setState];
}
// Before rendering a functional component
function updateFunctionComponent(fiber) {
wipFiber = fiber;
hookIndex = 0;
wipFiber.hooks = [];
const children = [fiber.type(fiber.props)];
reconcileChildren(fiber, children);
}
// Usage
function Counter() {
const [count, setCount] = useState(0);
return createElement('button',
{ onClick: () => setCount(c => c + 1) },
count
);
}
Implementation Hints:
Why order matters:
// Hooks are identified by call ORDER, not name
function Component() {
// Call 1 → hooks[0]
const [name, setName] = useState('');
// Call 2 → hooks[1]
const [age, setAge] = useState(0);
// Call 3 → hooks[2]
const [email, setEmail] = useState('');
}
// On re-render, hooks[0] must be name, hooks[1] must be age...
// That's why you can't put hooks in conditionals!
Learning milestones:
- Initial state works → First render has correct value
- setState triggers re-render → Updates cause new render
- State persists → Value carries across renders
- Multiple useState works → Hook index system works
Project 6: Implement useEffect Hook
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Hooks / Side Effects / Lifecycle
- Software or Tool: Your mini-React
- Main Book: React useEffect Documentation
What you’ll build: A working useEffect hook that runs side effects after render and supports cleanup and dependencies.
Why it teaches React internals: useEffect unifies componentDidMount, componentDidUpdate, and componentWillUnmount. Understanding its timing model is crucial.
Core challenges you’ll face:
- Running effects after commit → maps to effect timing
- Dependency comparison → maps to Object.is shallow compare
- Cleanup functions → maps to running previous cleanup before new effect
- Effect scheduling → maps to useEffect vs useLayoutEffect
Key Concepts:
- Effect Timing: After paint (useEffect) vs before paint (useLayoutEffect)
- Dependency Array: When to re-run
- Cleanup Pattern: Return function from effect
Difficulty: Advanced Time estimate: 1 week Prerequisites: Project 5 (useState)
Real world outcome:
function useEffect(callback, deps) {
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
const hasChanged = !oldHook || !deps ||
deps.some((dep, i) => !Object.is(dep, oldHook.deps[i]));
const hook = {
deps,
effect: hasChanged ? callback : null,
cleanup: oldHook?.cleanup
};
wipFiber.hooks.push(hook);
hookIndex++;
}
// After commit phase, run effects
function commitRoot() {
// Run cleanup from previous render
deletions.forEach(commitWork);
commitWork(wipRoot.child);
// Run effects
runEffects(wipRoot);
currentRoot = wipRoot;
wipRoot = null;
}
function runEffects(fiber) {
if (!fiber) return;
fiber.hooks?.forEach(hook => {
// Run previous cleanup
if (hook.cleanup) hook.cleanup();
// Run new effect
if (hook.effect) {
hook.cleanup = hook.effect();
}
});
runEffects(fiber.child);
runEffects(fiber.sibling);
}
// Usage
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(id); // Cleanup
}, []); // Empty deps = mount only
return createElement('div', null, count);
}
Implementation Hints:
Effect timing:
Render Phase Commit Phase After Paint
[build tree] -----> [update DOM] -----> [run useEffect]
↓
[run useLayoutEffect]
Dependency comparison:
function depsChanged(oldDeps, newDeps) {
if (!oldDeps || !newDeps) return true;
if (oldDeps.length !== newDeps.length) return true;
return oldDeps.some((dep, i) => !Object.is(dep, newDeps[i]));
}
Learning milestones:
- Effects run after render → Timing is correct
- Cleanup runs → Previous effect is cleaned up
- Dependencies work → Effect only runs when deps change
- Empty deps = mount only → Runs once
Project 7: Implement useRef Hook
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 2: Practical but Forgettable
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Hooks / Mutable References
- Software or Tool: Your mini-React
- Main Book: React useRef Documentation
What you’ll build: A useRef hook that provides a mutable container persisting across renders without triggering re-renders.
Why it teaches React internals: useRef is the simplest hook—just a stable object. But it reveals how React persists values without reactivity.
Core challenges you’ll face:
- Creating persistent object → maps to same object across renders
- Not triggering re-renders → maps to mutations don’t schedule updates
- Accessing DOM nodes → maps to ref prop handling
Key Concepts:
- Mutable Container: { current: value }
- Stable Identity: Same object every render
- DOM Access: Assigning ref.current = domNode
Difficulty: Intermediate Time estimate: 2-3 days Prerequisites: Project 5 (useState)
Real world outcome:
function useRef(initial) {
const oldHook = wipFiber.alternate?.hooks?.[hookIndex];
const hook = oldHook || { current: initial };
wipFiber.hooks.push(hook);
hookIndex++;
return hook; // Same object every time
}
// Usage
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return createElement('div', null,
createElement('input', { ref: inputRef }),
createElement('button', { onClick: focusInput }, 'Focus')
);
}
Implementation Hints:
Handling ref prop:
// When creating DOM, check for ref
function createDom(fiber) {
const dom = /* create element */;
// Assign ref
if (fiber.props.ref) {
fiber.props.ref.current = dom;
}
return dom;
}
Learning milestones:
- useRef returns stable object → Same ref across renders
- Mutations don’t re-render → ref.current = x doesn’t trigger update
- DOM refs work → Can access actual DOM nodes
Project 8: Implement Event Delegation
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Events / Performance / Delegation
- Software or Tool: Browser
- Main Book: React SyntheticEvent Documentation
What you’ll build: An event system that uses delegation (single listener at root) instead of attaching listeners to each element.
Why it teaches React internals: React doesn’t attach onClick to buttons—it uses event delegation for performance and consistency.
Core challenges you’ll face:
- Single root listener → maps to event delegation pattern
- Finding the target fiber → maps to mapping DOM to fibers
- Bubbling through fiber tree → maps to simulating event propagation
- SyntheticEvent wrapper → maps to cross-browser normalization
Resources for key challenges:
Key Concepts:
- Event Delegation: One listener catches all
- Fiber ↔ DOM Mapping: Finding fiber from DOM node
- Synthetic Events: Normalized event interface
Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 4 (Fiber)
Real world outcome:
// Store fiber reference on DOM node
function createDom(fiber) {
const dom = document.createElement(fiber.type);
dom.__fiber = fiber; // Link DOM → Fiber
return dom;
}
// Single listener at root
function setupEventDelegation(root) {
['click', 'change', 'input', 'keydown', 'keyup'].forEach(eventType => {
root.addEventListener(eventType, event => {
let fiber = event.target.__fiber;
// Walk up fiber tree, call handlers
while (fiber) {
const handler = fiber.props[`on${capitalize(eventType)}`];
if (handler) {
// Create synthetic event
const syntheticEvent = createSyntheticEvent(event);
handler(syntheticEvent);
if (syntheticEvent.isPropagationStopped) break;
}
fiber = fiber.parent;
}
});
});
}
function createSyntheticEvent(nativeEvent) {
return {
nativeEvent,
target: nativeEvent.target,
currentTarget: nativeEvent.currentTarget,
type: nativeEvent.type,
isPropagationStopped: false,
stopPropagation() {
this.isPropagationStopped = true;
nativeEvent.stopPropagation();
},
preventDefault() {
nativeEvent.preventDefault();
}
};
}
Implementation Hints:
Why delegation is better:
// Without delegation: 1000 buttons = 1000 listeners
buttons.forEach(btn => btn.addEventListener('click', handler));
// With delegation: 1000 buttons = 1 listener
root.addEventListener('click', event => {
// Find which button was clicked
const fiber = event.target.__fiber;
if (fiber.props.onClick) fiber.props.onClick(event);
});
Learning milestones:
- Root listener catches events → Delegation works
- Correct handler called → DOM → Fiber mapping works
- Bubbling works → Events propagate up fiber tree
- stopPropagation works → Can prevent bubbling
Project 9: Implement Reconciliation with Keys
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Reconciliation / Lists / Keys
- Software or Tool: Your mini-React
- Main Book: React Reconciliation Documentation
What you’ll build: Enhanced reconciliation that uses keys to efficiently reorder, insert, and delete list items.
Why it teaches React internals: Keys are the most misunderstood React concept. Understanding them requires understanding how reconciliation matches old and new children.
Core challenges you’ll face:
- Building key → fiber map → maps to O(1) lookup of old children
- Matching by key → maps to finding corresponding old fiber
- Detecting moves → maps to reordering optimization
- Handling index fallback → maps to when no key is provided
Key Concepts:
- Keys as Identity: Stable identity across renders
- Map-based Matching: O(n) reconciliation
- Move vs Replace: Reusing fibers for reordered items
Difficulty: Advanced Time estimate: 1 week Prerequisites: Projects 3-4 (Diffing, Fiber)
Real world outcome:
function reconcileChildren(wipFiber, elements) {
// Build map of old children by key
const oldFibers = {};
let oldFiber = wipFiber.alternate?.child;
while (oldFiber) {
const key = oldFiber.props.key ?? oldFiber.index;
oldFibers[key] = oldFiber;
oldFiber = oldFiber.sibling;
}
let prevSibling = null;
elements.forEach((element, index) => {
const key = element.props?.key ?? index;
const oldFiber = oldFibers[key];
delete oldFibers[key]; // Mark as used
let newFiber;
// Same type = update
if (oldFiber && oldFiber.type === element.type) {
newFiber = {
type: element.type,
props: element.props,
dom: oldFiber.dom, // Reuse DOM!
parent: wipFiber,
alternate: oldFiber,
effectTag: 'UPDATE'
};
}
// Different type = replace
else {
newFiber = {
type: element.type,
props: element.props,
dom: null,
parent: wipFiber,
alternate: null,
effectTag: 'PLACEMENT'
};
if (oldFiber) {
oldFiber.effectTag = 'DELETION';
deletions.push(oldFiber);
}
}
// Link siblings
if (index === 0) {
wipFiber.child = newFiber;
} else {
prevSibling.sibling = newFiber;
}
prevSibling = newFiber;
});
// Remaining old fibers are deletions
Object.values(oldFibers).forEach(fiber => {
fiber.effectTag = 'DELETION';
deletions.push(fiber);
});
}
Implementation Hints:
Why keys help:
// Without keys: [A, B, C] → [C, A, B]
// React compares by index:
// 0: A → C (different, replace)
// 1: B → A (different, replace)
// 2: C → B (different, replace)
// = 3 DOM operations
// With keys: [A:a, B:b, C:c] → [C:c, A:a, B:b]
// React matches by key:
// c: found at index 2, move to 0
// a: found at index 0, move to 1
// b: found at index 1, move to 2
// = 0 DOM recreations, just moves
Learning milestones:
- Key matching works → Correct old fiber found
- Reordering reuses DOM → No unnecessary recreation
- Additions/deletions work → New items added, old removed
- Performance improved → List updates are fast
Project 10: Implement Batched Updates
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Performance / Update Batching
- Software or Tool: Your mini-React
- Main Book: React 18 Automatic Batching
What you’ll build: Update batching that combines multiple setState calls into a single re-render.
Why it teaches React internals: Without batching, setState + setState = 2 renders. React batches them into 1 render for performance.
Core challenges you’ll face:
- Collecting updates → maps to queue of pending updates
- Scheduling a single render → maps to microtask or setTimeout
- Flushing at the right time → maps to event handler boundaries
Key Concepts:
- Update Queue: Collecting setState calls
- Scheduling: When to flush updates
- Automatic Batching: React 18’s improvement
Difficulty: Intermediate Time estimate: 3-4 days Prerequisites: Project 5 (useState)
Real world outcome:
let isBatchingUpdates = false;
let pendingUpdates = [];
function scheduleUpdate(fiber) {
pendingUpdates.push(fiber);
if (!isBatchingUpdates) {
isBatchingUpdates = true;
// Use microtask for automatic batching
queueMicrotask(() => {
flushUpdates();
isBatchingUpdates = false;
});
}
}
function flushUpdates() {
// Start render from root
wipRoot = {
dom: currentRoot.dom,
props: currentRoot.props,
alternate: currentRoot
};
nextUnitOfWork = wipRoot;
pendingUpdates = [];
}
// Usage
function Counter() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
const handleClick = () => {
setCount(c => c + 1); // Queued
setFlag(f => !f); // Queued
// Only ONE re-render happens!
};
console.log('Render'); // Logs once per click
return createElement('button', { onClick: handleClick }, count);
}
Implementation Hints:
React 18 automatic batching:
// React 17: Only batched in event handlers
onClick={() => {
setA(1); // Batched
setB(2); // Batched
});
setTimeout(() => {
setA(1); // NOT batched (React 17)
setB(2); // NOT batched (React 17)
});
// React 18: Batched EVERYWHERE automatically
setTimeout(() => {
setA(1); // Batched!
setB(2); // Batched!
});
Learning milestones:
- Multiple setStates = 1 render → Batching works
- Works in event handlers → Sync updates batched
- Works in setTimeout → Async updates batched
- Correct final state → All updates applied
Project 11: Implement Context (useContext)
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: State Management / Context
- Software or Tool: Your mini-React
- Main Book: React Context Documentation
What you’ll build: A Context system with createContext, Provider, and useContext for sharing state without prop drilling.
Why it teaches React internals: Context is React’s built-in state sharing. Understanding how values flow down the tree reveals React’s rendering model.
Core challenges you’ll face:
- Creating context object → maps to Provider + Consumer + default value
- Provider component → maps to wrapping children with value
- Walking up tree for value → maps to finding nearest Provider
- Re-rendering consumers → maps to when context value changes
Key Concepts:
- Provider/Consumer Pattern: Component-based value distribution
- Tree Walking: Finding nearest provider
- Subscription: Updating when context changes
Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 5 (useState)
Real world outcome:
function createContext(defaultValue) {
const context = {
_currentValue: defaultValue,
Provider: null,
Consumer: null
};
context.Provider = function Provider({ value, children }) {
context._currentValue = value;
return children;
};
return context;
}
function useContext(context) {
// In real React, this walks up the fiber tree
// to find the nearest Provider
return context._currentValue;
}
// Usage
const ThemeContext = createContext('light');
function App() {
const [theme, setTheme] = useState('dark');
return createElement(ThemeContext.Provider, { value: theme },
createElement(Toolbar, null),
createElement('button',
{ onClick: () => setTheme(t => t === 'dark' ? 'light' : 'dark') },
'Toggle'
)
);
}
function Toolbar() {
return createElement(ThemedButton, null);
}
function ThemedButton() {
const theme = useContext(ThemeContext);
return createElement('button', { className: theme }, 'I am themed');
}
Implementation Hints:
Real implementation walks fiber tree:
function useContext(context) {
let fiber = wipFiber;
// Walk up looking for Provider
while (fiber) {
if (fiber.type === context.Provider) {
return fiber.props.value;
}
fiber = fiber.parent;
}
// No provider found, use default
return context._defaultValue;
}
Learning milestones:
- createContext works → Returns Provider + default
- useContext reads value → Gets current context value
- Nested providers work → Inner value overrides outer
- Updates propagate → Context change re-renders consumers
Project 12: Implement Concurrent Features (Basic)
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript
- Alternative Programming Languages: TypeScript
- Coolness Level: Level 5: Pure Magic (Super Cool)
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 4: Expert
- Knowledge Area: Concurrent Rendering / Scheduling
- Software or Tool: Your mini-React
- Main Book: React 18 Concurrent Features
What you’ll build: Basic concurrent features—time slicing with priority and a simplified useTransition hook.
Why it teaches React internals: Concurrent rendering is React’s most advanced feature. Understanding it shows you how React keeps apps responsive during heavy work.
Core challenges you’ll face:
- Time slicing → maps to yielding to browser between work
- Priority levels → maps to urgent vs non-urgent updates
- Interruptible rendering → maps to discarding stale work
- useTransition → maps to marking updates as low priority
Resources for key challenges:
Key Concepts:
- Time Slicing: 5ms work chunks
- Priority Lanes: Urgent vs deferred updates
- Transitions: Non-blocking updates
Difficulty: Expert Time estimate: 2 weeks Prerequisites: Projects 4-6 (Fiber, hooks)
Real world outcome:
// Priority levels
const ImmediatePriority = 1;
const UserBlockingPriority = 2;
const NormalPriority = 3;
const LowPriority = 4;
const IdlePriority = 5;
let currentPriority = NormalPriority;
function scheduleCallback(priority, callback) {
const task = { priority, callback };
taskQueue.push(task);
taskQueue.sort((a, b) => a.priority - b.priority);
if (!isScheduled) {
isScheduled = true;
requestIdleCallback(workLoop);
}
}
function workLoop(deadline) {
while (taskQueue.length > 0 && deadline.timeRemaining() > 1) {
const task = taskQueue.shift();
task.callback();
}
if (taskQueue.length > 0) {
requestIdleCallback(workLoop);
} else {
isScheduled = false;
}
}
// useTransition marks updates as non-urgent
function useTransition() {
const [isPending, setIsPending] = useState(false);
const startTransition = callback => {
setIsPending(true);
scheduleCallback(LowPriority, () => {
callback();
setIsPending(false);
});
};
return [isPending, startTransition];
}
// Usage
function Search() {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const [isPending, startTransition] = useTransition();
const handleChange = e => {
// Urgent: update input immediately
setQuery(e.target.value);
// Non-urgent: update results later
startTransition(() => {
setResults(search(e.target.value));
});
};
return createElement('div', null,
createElement('input', { value: query, onChange: handleChange }),
isPending ? 'Loading...' : results.map(r => createElement('div', null, r))
);
}
Implementation Hints:
Time slicing in work loop:
function workLoopConcurrent() {
while (nextUnitOfWork && !shouldYield()) {
nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}
}
function shouldYield() {
// Yield after 5ms of work
return performance.now() - workStartTime > 5;
}
Learning milestones:
- Time slicing works → UI stays responsive during render
- Priority works → Urgent updates happen first
- useTransition works → Non-blocking state updates
- isPending works → Can show loading state
Project 13: Read React Source Code
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript (reading)
- Alternative Programming Languages: N/A
- Coolness Level: Level 5: Pure Magic (Super Cool)
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 4: Expert
- Knowledge Area: Source Code Analysis
- Software or Tool: React source, IDE
- Main Book: React Source Code
What you’ll build: A documented deep-dive into React’s actual source code, tracing key code paths and understanding real implementation details.
Why it teaches React internals: You’ve built simplified versions—now see how the React team does it. Their code is well-organized and teachable.
Core challenges you’ll face:
- Navigating monorepo → maps to understanding package structure
- Tracing execution → maps to following function calls
- Understanding optimizations → maps to why certain patterns are used
- Reading Flow types → maps to type annotations in React source
Key Concepts:
- Monorepo Structure: packages/react, packages/react-dom, etc.
- Scheduler Package: Priority and time slicing
- Reconciler Package: Fiber and rendering
Difficulty: Expert Time estimate: 2-4 weeks Prerequisites: All previous projects
Real world outcome:
# My React Source Code Study
## Package Structure
- packages/react - createElement, hooks, context
- packages/react-dom - DOM rendering, event system
- packages/react-reconciler - Fiber, reconciliation (shared)
- packages/scheduler - Priority scheduling
## Key Files
### packages/react-reconciler/src/ReactFiber.js
- createFiber() - Creates fiber nodes
- FiberNode class with all the fields I implemented
### packages/react-reconciler/src/ReactFiberWorkLoop.js
- workLoopSync() - Legacy mode rendering
- workLoopConcurrent() - Concurrent rendering with shouldYield
### packages/react-reconciler/src/ReactFiberHooks.js
- renderWithHooks() - Sets up hooks for a component
- useState implementation uses useReducer internally!
## Key Insight: useState is useReducer
function useState(initialState) {
return useReducer(basicStateReducer, initialState);
}
function basicStateReducer(state, action) {
return typeof action === 'function' ? action(state) : action;
}
Implementation Hints:
Files to study:
packages/react/src/ReactElement.js- createElementpackages/react-reconciler/src/ReactFiber.js- Fiber structurepackages/react-reconciler/src/ReactFiberHooks.js- Hookspackages/react-reconciler/src/ReactFiberWorkLoop.js- Render looppackages/scheduler/src/forks/Scheduler.js- Scheduling
Learning milestones:
- Navigate the source → Find what you’re looking for
- Trace a render → Follow createElement to DOM update
- Trace a hook → Follow useState from call to re-render
- Understand real optimizations → Why React does things certain ways
Project 14: Build Complete Mini-React
- File: LEARN_REACT_INTERNALS.md
- Main Programming Language: JavaScript/TypeScript
- Alternative Programming Languages: N/A
- Coolness Level: Level 5: Pure Magic (Super Cool)
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 5: Master
- Knowledge Area: Complete Framework
- Software or Tool: Node.js, Browser
- Main Book: Build Your Own React (pomb.us)
What you’ll build: A complete mini-React combining all previous projects—createElement, Fiber, reconciliation, hooks, events, and concurrent features.
Why it’s the ultimate capstone: Building a working React from scratch proves you understand React at the deepest level.
Time estimate: 1-2 months Prerequisites: All previous projects
Real world outcome:
// Your mini-React in action
import { createElement, render, useState, useEffect, useRef } from './mini-react';
function App() {
const [count, setCount] = useState(0);
const [items, setItems] = useState(['A', 'B', 'C']);
const inputRef = useRef(null);
useEffect(() => {
console.log(`Count is now ${count}`);
}, [count]);
return createElement('div', { className: 'app' },
createElement('h1', null, `Count: ${count}`),
createElement('button', { onClick: () => setCount(c => c + 1) }, '+'),
createElement('button', { onClick: () => setCount(c => c - 1) }, '-'),
createElement('input', { ref: inputRef }),
createElement('button', { onClick: () => inputRef.current.focus() }, 'Focus'),
createElement('ul', null,
items.map((item, i) =>
createElement('li', { key: item },
item,
createElement('button', {
onClick: () => setItems(items.filter((_, j) => j !== i))
}, 'x')
)
)
),
createElement('button', {
onClick: () => setItems([...items, String.fromCharCode(65 + items.length)])
}, 'Add Item')
);
}
render(createElement(App), document.getElementById('root'));
Learning milestones:
- Basic rendering works → Static elements appear
- State works → useState triggers re-renders
- Effects work → useEffect runs after render
- Lists with keys work → Efficient reconciliation
- Events work → Event delegation handles clicks
- Everything together → Complete React-like experience
Project Comparison Table
| Project | Difficulty | Time | Key Concept | Fun Factor |
|---|---|---|---|---|
| 1. createElement | ⭐ | 2-3 days | JSX/Elements | ⭐⭐⭐ |
| 2. DOM Renderer | ⭐⭐ | 3-4 days | Rendering | ⭐⭐⭐ |
| 3. Diffing Algorithm | ⭐⭐⭐ | 1 week | Reconciliation | ⭐⭐⭐⭐ |
| 4. Fiber Work Loop | ⭐⭐⭐ | 1-2 weeks | Fiber Architecture | ⭐⭐⭐⭐⭐ |
| 5. useState | ⭐⭐⭐ | 1 week | Hooks | ⭐⭐⭐⭐⭐ |
| 6. useEffect | ⭐⭐⭐ | 1 week | Effects/Lifecycle | ⭐⭐⭐⭐ |
| 7. useRef | ⭐⭐ | 2-3 days | Mutable Refs | ⭐⭐⭐ |
| 8. Event Delegation | ⭐⭐ | 1 week | Events | ⭐⭐⭐⭐ |
| 9. Keys Reconciliation | ⭐⭐⭐ | 1 week | List Rendering | ⭐⭐⭐⭐ |
| 10. Batched Updates | ⭐⭐ | 3-4 days | Performance | ⭐⭐⭐ |
| 11. Context | ⭐⭐ | 1 week | State Sharing | ⭐⭐⭐ |
| 12. Concurrent Features | ⭐⭐⭐⭐ | 2 weeks | Concurrent Mode | ⭐⭐⭐⭐⭐ |
| 13. Source Code Study | ⭐⭐⭐⭐ | 2-4 weeks | Real Implementation | ⭐⭐⭐⭐ |
| 14. Complete Mini-React | ⭐⭐⭐⭐⭐ | 1-2 months | Everything | ⭐⭐⭐⭐⭐ |
Recommended Learning Path
Phase 1: Foundations (2-3 weeks)
Understand the basic building blocks:
- Project 1: createElement - Virtual DOM elements
- Project 2: DOM Renderer - Elements to real DOM
- Project 3: Diffing Algorithm - Minimal updates
Phase 2: Fiber Architecture (2-3 weeks)
Understand incremental rendering:
- Project 4: Fiber Work Loop - Interruptible rendering
- Project 8: Event Delegation - How events work
- Project 9: Keys Reconciliation - Efficient lists
Phase 3: Hooks (2-3 weeks)
Understand state and effects:
- Project 5: useState - State management
- Project 6: useEffect - Side effects
- Project 7: useRef - Mutable references
- Project 11: Context - State sharing
Phase 4: Advanced Features (2-3 weeks)
Understand performance optimizations:
- Project 10: Batched Updates - Update coalescing
- Project 12: Concurrent Features - Time slicing
Phase 5: Mastery (4-6 weeks)
Deep understanding:
- Project 13: Source Code Study - Read real React
- Project 14: Complete Mini-React - Build it all
Summary
| # | Project | Main Language |
|---|---|---|
| 1 | Build Your Own createElement | JavaScript |
| 2 | Build Your Own Renderer | JavaScript |
| 3 | Implement Diffing Algorithm | JavaScript |
| 4 | Build Fiber Work Loop | JavaScript |
| 5 | Implement useState | JavaScript |
| 6 | Implement useEffect | JavaScript |
| 7 | Implement useRef | JavaScript |
| 8 | Implement Event Delegation | JavaScript |
| 9 | Implement Keys Reconciliation | JavaScript |
| 10 | Implement Batched Updates | JavaScript |
| 11 | Implement Context | JavaScript |
| 12 | Implement Concurrent Features | JavaScript |
| 13 | Read React Source Code | JavaScript |
| 14 | Build Complete Mini-React | JavaScript |
Resources
Essential Tutorials
- Build Your Own React - Rodrigo Pombo (pomb.us)
- Didact - Step-by-step React implementation
- How to Write Your Own Virtual DOM
Architecture Deep Dives
- React Fiber Architecture - Andrew Clark
- Deep Dive into React Fiber - LogRocket
- Inside Fiber
Hooks Internals
- How React Hooks Work Under the Hood
- Under the Hood of React’s Hooks
- Deep Dive: How Do React Hooks Really Work?
Official Documentation
- Reconciliation - React docs
- React Fiber Scheduler
Source Code
- React GitHub - Official source
- Key directories:
packages/react,packages/react-reconciler,packages/scheduler
Total Estimated Time: 4-6 months of dedicated study
After completion: You’ll understand React at the level of its creators. You’ll debug any React issue instantly, write highly performant code naturally, and be able to contribute to React itself or build your own UI library.