"Every 100ms of latency costs 1% in sales."
Google's new metric, Interaction to Next Paint (INP), punishes apps that freeze on click. If your event handler takes >200ms, you fail. Period.
02. Fiber Architecture Deep Dive
To optimize React, you must understand Fiber. Fiber is a reimplementation of the stack, specialized for React components. It allows React to pause work (rendering) and come back to it later.
The "Work Loop"
- Stack Reconciler (React 15): Recursive. Once it starts rendering, it cannot stop until the bottom of the tree. (Blocks main thread).
- Fiber Reconciler (React 16+): Iterative. It breaks rendering into "Units of Work". It checks the frame budget (5ms) after every unit. If time is up, it yields to the browser.
Deep Dive: The React Compiler (React 19)
Forget manual memoization. The new React Compiler automatically memoizes components and hooks for you. It understands your code at a low level and inserts `useMemo` where appropriate, ensuring fine-grained updates without the headache.
03. Render vs. Commit Phases
Phase 1: Render (Slow)
React calls your component functions. It compares the old Virtual DOM with the new one.
Key: This is pure JavaScript calculation. No DOM touches. May happen multiple times.
Phase 2: Commit (Fast)
React applies the changes to the real DOM (insert, update, delete).
Key: This must happen in one go to prevent visual glitches.
Optimization Strategy: Prevent the "Render Phase" from running unnecessarily.
04. Virtualization (Windowing)
If you render 10,000 items, you create 10,000 DOM nodes. The browser's Layout/Paint steps will choke. Virtualization renders only what is visible + a small buffer.
"Never render a list without virtualization if it can grow > 100 items."
05. Memoization Strategy
Using `React.memo` everywhere is an anti-pattern (it adds comparison overhead). Use it only on heavy components or huge lists.
// ❌ BAD: Wrapper recreated every render <HeavyComponent onClick={() => console.log('click')} /> // ✅ GOOD: Stable reference const handleClick = useCallback(() => console.log('click'), []); <HeavyComponent onClick={handleClick} />
06. Concurrent Features
Sometimes you must do heavy work. In React 18, you can mark updates as "Transition" (Low Priority). This tells React: "If the user types, interrupt this heavy rendering task to update the input immediately."
const [isPending, startTransition] = useTransition();
// Typing feels instant (High Priority)
setInputValue(e.target.value);
startTransition(() => {
// Chart re-render happens in background (Low Priority)
setChartData(heavyCalculation(e.target.value));
});
07. Senior Takeaways
- 1. Measure First: Never optimize without the React Profiler. You are probably optimizing the wrong thing.
- 2. State Colocation: Move state down. If only the `Button` needs the state, don't put it in `App`. This prevents re-rendering the whole tree.
- 3. Context Splitting: Don't put everything in one `AppContext`. Split it into `UserContext`, `ThemeContext`, etc., so consumers don't re-render unnecessarily.
08. FPS Render Lab
Simulate a heavy workload (blocking the main thread) and see how Virtualization and Concurrency fix the frame rate.