React Performance: Render and Commit 🎬
Think of React like a restaurant kitchen. Orders come in, chefs prepare food, and finally plates go out to customers. React works the same way!
The Big Picture: Two-Phase Magic ✨
Imagine you’re making a pizza. You don’t just throw ingredients on a plate and serve it. First, you plan and prepare (Render Phase), then you put it in the oven and serve (Commit Phase).
React does exactly this with your screen!
graph TD A["State Changes"] --> B["Render Phase"] B --> C["Commit Phase"] C --> D["Screen Updates!"]
🎨 The Render Phase
What is it? React figures out WHAT should change.
Think of it like an architect drawing blueprints. No walls are built yet. Just planning!
Key Facts:
- React calls your component functions
- Calculates the “Virtual DOM” (a draft of changes)
- Can be paused or restarted! (This is huge!)
- No touching the actual screen yet
Simple Example:
function Counter({ count }) {
// Render phase: React runs
// this code to see what to show
return <p>Count: {count}</p>;
}
When count changes from 5 to 6:
- React calls
Counter({ count: 6 }) - Gets back
<p>Count: 6</p> - Compares with old
<p>Count: 5</p> - Notes: “Just change the text!”
🖌️ The Commit Phase
What is it? React actually UPDATES the screen.
The architect is done planning. Now the builders get to work!
Key Facts:
- Happens AFTER render phase
- Actually touches the DOM (real screen)
- Cannot be interrupted
- Fast! React applies only what changed
What happens:
Old Screen: "Count: 5"
↓
React commits the change
↓
New Screen: "Count: 6"
🎯 Remember: Render = Planning, Commit = Doing
🕸️ Fiber Architecture
The Secret Sauce Behind React’s Speed
Imagine you’re cleaning your room. Old React would clean EVERYTHING at once and ignore you until done. Fiber React cleans a bit, checks if mom needs you, then continues.
What is Fiber?
Fiber is React’s internal work system. Each component becomes a “fiber” (a small unit of work).
graph TD A["App Fiber"] --> B["Header Fiber"] A --> C["Main Fiber"] A --> D["Footer Fiber"] C --> E["Button Fiber"] C --> F["List Fiber"]
Why Fiber Matters:
| Old React | Fiber React |
|---|---|
| All or nothing | Work in chunks |
| Can’t pause | Can pause anytime |
| Janky animations | Smooth 60fps |
Real Example:
- User clicks button
- React starts updating 1000 items
- User types in search box
- Fiber: “Wait! Typing is urgent!”
- Pauses items, handles typing first
- Continues items after
📦 Batching Behavior
React’s Way of Being Smart
Imagine sending 10 separate texts vs one message with 10 points. Batching is sending everything together!
What Gets Batched?
React groups multiple state updates into ONE render:
function handleClick() {
setCount(1); // React: "Noted!"
setName('Bob'); // React: "Noted!"
setAge(25); // React: "Noted!"
// ONE render happens, not three!
}
Batching Rules:
âś… Batched (one render):
- All updates in event handlers
- All updates in useEffect
- All updates in setTimeout/Promise (React 18+)
// React 18: ALL batched!
setTimeout(() => {
setA(1);
setB(2);
// Only ONE re-render!
}, 100);
đź’ˇ Tip: Want to force separate renders? Use
flushSync()(but avoid if possible!)
🚦 State Queue and Lanes
Priority Express Lane System
Think of a hospital emergency room. Heart attack patient goes before a sprained ankle. React has the same priority system!
The State Queue
When you call setState, React doesn’t update immediately. It adds to a queue:
setCount(c => c + 1); // Added to queue
setCount(c => c + 1); // Added to queue
setCount(c => c + 1); // Added to queue
// Queue processes: 0 → 1 → 2 → 3
Lanes Explained
Lanes are priority levels. Higher priority = faster response.
graph LR A["🚨 User Input"] --> B["Sync Lane"] C["📱 Animations"] --> D["Transition Lane"] E["📊 Data Fetch"] --> F["Default Lane"] G["🔧 Background"] --> H["Idle Lane"]
| Lane Type | Priority | Example |
|---|---|---|
| Sync | đź”´ Highest | Click, Type |
| Transition | 🟡 High | Page navigation |
| Default | 🟢 Normal | Data loading |
| Idle | 🔵 Low | Analytics |
Real Example:
import { startTransition } from 'react';
// HIGH priority (immediate)
setInputValue(e.target.value);
// LOWER priority (can wait)
startTransition(() => {
setSearchResults(filterData());
});
🔄 Re-render Triggers
What Makes React Update?
A re-render is React asking: “Has anything changed?” Here’s what triggers it:
The 4 Triggers:
- State changes (most common)
const [count, setCount] = useState(0);
setCount(5); // Triggers re-render!
- Props change
// Parent passes new prop
<Child name="Alice" /> // was "Bob"
// Child re-renders!
- Context changes
// Any component using this context
const theme = useContext(ThemeContext);
// Re-renders when theme changes!
- Parent re-renders
function Parent() {
const [x, setX] = useState(0);
return <Child />; // Child re-renders too!
}
Common Mistakes:
❌ This won’t trigger re-render:
const obj = { name: 'Bob' };
obj.name = 'Alice'; // Mutation!
setUser(obj); // Same reference = no update
âś… This will:
setUser({ ...obj, name: 'Alice' });
// New object = re-render!
⏰ React Scheduling
The Traffic Controller
React doesn’t do everything immediately. It schedules work smartly, like a smart traffic light!
How Scheduling Works:
graph TD A["New Work Arrives"] --> B{Check Priority} B -->|High| C["Do Now!"] B -->|Medium| D["Add to Queue"] B -->|Low| E["Do When Free"] C --> F["Render + Commit"] D --> F E --> F
Key Scheduling Concepts:
Time Slicing:
- React works in 5ms chunks
- Checks “Do I have time for more?”
- If not, pauses for browser to breathe
Concurrent Features:
// useTransition - mark updates as low priority
const [isPending, startTransition] = useTransition();
startTransition(() => {
// This update can wait
setFilteredList(heavyFilter(data));
});
// Suspense - pause rendering until ready
<Suspense fallback={<Loading />}>
<SlowComponent />
</Suspense>
The Scheduler Priorities:
| Priority | When Used |
|---|---|
| Immediate | User clicks/types |
| User-blocking | Animations |
| Normal | Data updates |
| Low | Background work |
| Idle | When nothing else |
🎯 Putting It All Together
Here’s how everything connects:
graph TD A["User Action"] --> B["State Update"] B --> C["Added to Queue"] C --> D{Scheduler Checks} D --> E["Lane Assignment"] E --> F["Render Phase"] F --> G["Fiber Work Units"] G --> H{Batched?} H -->|Yes| I["Wait for More"] H -->|No| J["Commit Phase"] I --> J J --> K["Screen Updates!"]
đź§ Quick Summary
| Concept | One-Liner |
|---|---|
| Render Phase | Planning what changes (can pause) |
| Commit Phase | Actually updating screen (can’t pause) |
| Fiber | Work broken into tiny pausable units |
| Batching | Multiple updates → one render |
| Lanes | Priority system for updates |
| Triggers | State, props, context, parent |
| Scheduling | Smart timing of all work |
🎉 You Made It!
Now you understand how React thinks! Every time your app updates, React:
- Gets triggered (state/props/context)
- Adds work to queue with priority (lanes)
- Schedules when to do it
- Works in small chunks (Fiber)
- Batches what it can
- Renders (plans changes)
- Commits (updates screen)
You’re now in the top 10% of React developers who understand this! 🚀
