90% of React Developers Optimize Re-Renders Incorrectly
Most React developers optimize re-renders the wrong way. Where React performance actually goes and which fixes help, plus a checklist for applying them.
This article is published in English.
Sources: 90% of React Developers Optimize Re-Renders Incorrectly — Here’s What Actually Works
The following notes reconstruct a practical path around “90% of React Developers Optimize Re-Renders Incorrectly — Here’s What Actually Works”. Emphasis stays on contracts, checks, and drop-in code placeholders rather than motivational framing. When working through the Overview stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
The Real Problem: We Don’t Understand When React Re-Renders
The The Real Problem We stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
The Day you Finally Opened React Profiler
The The Day you Finally stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
The Core Truth: Re-Renders Aren’t the Enemy — Unnecessary Ones Are
The The Core Truth Re-Renders stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs. The The Core Truth Re-Renders stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Section 1: The Mental Model That Finally Made React Click
For the Section 1 The Mental stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Prefer structured outputs with schema validation over free-form prose when the next step is code or a tool call.
React = Function Execution Engine
For the React Function Execution Engine stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Colocate state with the component that owns the mutation. Lifting everything to a global store makes timing bugs harder to see.
Component(props) → JSX
Section 2: Why Your Components Re-Render More Than You Think
For the Section 2 Why Your stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Colocate state with the component that owns the mutation. Lifting everything to a global store makes timing bugs harder to see. For the Section 2 Why Your stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
1. Inline Objects & Functions
When working through the 1 Inline Objects Functions stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Treat effects as synchronization with the outside world, not as a substitute for derived values during render.
<MyComponent options={{ theme: "dark" }} />
{} !== {}
onClick={() => doSomething()}
2. State Lifted Too High
When working through the 2 State Lifted Too stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Treat effects as synchronization with the outside world, not as a substitute for derived values during render.
3. Derived State Stored as State
When working through the 3 Derived State Stored stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Treat effects as synchronization with the outside world, not as a substitute for derived values during render. When working through the 3 Derived State Stored stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
const [filtered, setFiltered] = useState([]);
useEffect(() => {
setFiltered(items.filter(...));
}, [items]);
Section 3: The Rule That Changed Everything for Me
The Section 3 The Rule stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
Section 4: The 4 Levels of React Re-Render Control
The Section 4 The 4 stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
Level 1: Structural Optimization (Most Important)
The Level 1 Structural Optimization stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs. The Level 1 Structural Optimization stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Level 2: Memoization (When Needed)
For the Level 2 Memoization When stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Colocate state with the component that owns the mutation. Lifting everything to a global store makes timing bugs harder to see.
Level 3: Referential Stability
For the Level 3 Referential Stability stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Colocate state with the component that owns the mutation. Lifting everything to a global store makes timing bugs harder to see.
const handler = () => doSomething();
const handler = useCallback(() => {
doSomething();
}, []);
const config = useMemo(() => ({
theme: "dark"
}), []);
Level 4: Architectural Isolation
For the Level 4 Architectural Isolation stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Colocate state with the component that owns the mutation. Lifting everything to a global store makes timing bugs harder to see. For the Level 4 Architectural Isolation stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Section 5: React.memo — The Most Misused Optimization
When working through the Section 5 React memo stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Treat effects as synchronization with the outside world, not as a substitute for derived values during render.
When React.memo Does NOTHING
When working through the When React memo Does stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Treat effects as synchronization with the outside world, not as a substitute for derived values during render.
When React.memo Shines
When working through the When React memo Shines stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Treat effects as synchronization with the outside world, not as a substitute for derived values during render. When working through the When React memo Shines stage, write down the contract first: required inputs, success signal, and what happens on partial failure. That checklist keeps later code changes honest. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
Section 6: The useCallback Trap
The Section 6 The useCallback stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
Section 7: The Hidden Cost of Context
The Section 7 The Hidden stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
Bad:
The Bad stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
<AuthContext.Provider value={{ user, theme }}>
Better:
The Better stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Prefer small, testable units over sprawling scripts. When a step fails, the failure should point at a single responsibility rather than a tangled pipeline. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
<UserContext />
<ThemeContext />
Section 8: Lists, Keys, and the Illusion of Stability
The Section 8 Lists Keys stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
items.map((item, i) => <Row key={i} />)
items.map(item => <Row key={item.id} />)
Section 9: the Personal Performance Checklist
The Section 9 the Personal stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Record timings and token or query cost next to functional results. Cost visibility early prevents surprise bills when the path moves from demo to shared environments. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
Section 10: The Big Mindset Shift
The Section 10 The Big stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Keep configuration outside application code. Environment files, secret stores, and feature flags belong in one place operators can audit without reading the whole graph. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs.
Final Thoughts: The Real Secret
The Final Thoughts The Real stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Document the happy path and the recovery path together. Retries, human gates, and dead-letter handling are part of the product, not later polish. Keep render work cheap and push expensive derivation behind memoization only after measuring. Premature memo can hide stale props bugs. The Final Thoughts The Real stage works best when treated as a measurable surface. Capture one golden transcript, one failure case, and the rollback note before expanding scope. Treat this stage as a contract between inputs and validated outputs. Name the artifacts, define success checks, and refuse silent partial completion.
React Performance & Optimization
For the React Performance Optimization stage, define the inputs, the owner of the step, and the exit criteria before changing code. Operators should be able to re-run the step from a known checkpoint without guessing hidden state.