This article is published in English.
React performance in 2026: architecture before useMemo
Let the React Compiler handle routine memoization, push work into Server Components, and measure real bottlenecks before sprinkling useMemo and useCallback through every file.
For a long stretch, React performance advice followed a ritual. Spot a re-render, wrap with memo. See a calculation, wrap with useMemo. Pass a function, wrap with useCallback. Component feels large, split it. Repeat. That playbook worked often enough to become muscle memory.
React’s center of gravity has shifted. The APIs did not suddenly become useless. What changed is that optimization is moving from something every component hand-manages toward something frameworks and compilers can apply automatically. Teams building React and Next.js apps in 2026 should update the mental model accordingly.
The Old React Optimization Mindset
A familiar component pattern looked like this:
const filteredUsers = useMemo(
() => users.filter((user) => user.isActive),
[users]
);
const handleSelect = useCallback(
(id: string) => {
selectUser(id);
},
[selectUser]
);return (
<UserList
users={filteredUsers}
onSelect={handleSelect}
/>
);
The intent was clear: on the next render, skip filtering users again, skip recreating the callback, and spare memoized children. The hidden bill is cognitive load. Developers now juggle:
dependencies
references
closures
memoization
stale values
component boundaries
One of the cheapest ways to introduce bugs is to “optimize” work that was never hot.
Enter the React Compiler
The compiler invites a different contract. Instead of constantly telling React to remember a value, you write ordinary component code and let compilation decide where memoization helps:
function ActiveUsersList({ users }) {
const filteredUsers = users.filter(
(user) => user.isActive
);
return (
<ul>
{filteredUsers.map((user) => (
<li key={user.id}>
{user.name}
</li>
))}
</ul>
);
}
Readable filters, no handwritten memoization, no dependency arrays to keep honest. The compiler analyzes the component and inserts appropriate optimizations. That is a philosophical change, not a cosmetic one.
But Don’t Delete Every useMemo
A common overreaction is to strip every useMemo, useCallback, and memo on day one. That is too blunt. Existing call sites may encode intentional caching; compiler coverage depends on React version, config, and code shape. A better default: do not manually optimize first—measure first. Let the compiler take the safe cases. Profile before adding hand-tuned hooks. Keep explicit memoization where it is deliberate and proven. The aim is less needless complexity, not a lower hook count for its own sake.
Performance Is Moving Up the Stack
Preventing child re-renders is only one slice of modern React cost. A typical Next.js request path looks like:
Browser
↓
React
↓
Next.js
↓
Server Components
↓
Data fetching
↓
Database
↓
External APIs
A three-second page may have nothing to do with React reconciliation. Slow queries, chatty APIs, fat bundles, sequential fetches, heavy images, unnecessary client components, weak caching, or expensive server work dominate. Another useMemo will not fix those.
Server Components Change the Equation
Server Components—especially via Next.js—move work off the browser. The traditional shape:
Traditional approach
Server
↓
Large JavaScript bundle
↓
Browser
↓
Render everything
A more server-oriented flow:
Server
├── Fetch data
├── Render server components
└── Send necessary result
↓
Browser
↓
Interactive components
Less JavaScript to download and execute is a larger lever than scattering useCallback through leaf components.
The New Question: “Does This Need to Be Client-Side?”
That question is now one of the highest-value prompts in React architecture. An entire dashboard need not be a Client Component. A split such as:
Dashboard
├── Server
│ ├── Customer summary
│ ├── Revenue
│ ├── Recent jobs
│ └── Invoice totals
│
└── Client
├── Date picker
├── Filters
└── Interactive chart
keeps interactivity where it must live and leaves summary data on the server. Performance becomes an ownership decision, not only a hook decision.
Stop Optimizing What You Haven’t Measured
Intuition still pushes people from:
users.map(...)
straight to “this needs memoization.” The map might cost under a millisecond while five sequential API calls burn the budget. Measure first with React DevTools Profiler, browser Performance panels, Lighthouse, Next.js tooling, Web Vitals, and server or database metrics. Locate the bottleneck, then fix that bottleneck.
The New Performance Checklist
Prefer this order over starting with:
useMemo
useCallback
React.memo
1. Reduce JavaScript
Does this component truly need to run in the browser?
2. Improve data fetching
Watch for:
waterfalls
duplicate requests
unnecessary requests
slow APIs
3. Cache intelligently
Stop refetching data that barely changes.
4. Optimize database queries
React cannot paper over a terrible query plan.
5. Reduce bundle size
Every casual dependency becomes payload.
6. Optimize images and assets
Large media still dominates many load timelines.
7. Measure rendering
Only after real render costs appear should component-level memoization enter the conversation.
What Happens to useMemo and useCallback?
They remain tools, not defaults. Old reflex: “I should probably memoize this.” Better reflex: “Do I have evidence this needs memoization?” Genuine expense justifies:
const value = useMemo(
() => expensiveCalculation(data),
[data]
);
String concatenation rarely does:
const fullName = useMemo(
() => `${firstName} ${lastName}`,
[firstName, lastName]
);
TypeScript Matters Too
Runtime is not the only performance surface. Refactor speed is developer performance. Strong types make large React codebases safer to change:
type Customer = {
id: string;
name: string;
email: string;
active: boolean;
};
When a component or API contract shifts, the typechecker shows breakage immediately—especially valuable when AI assistants generate large diffs that must still fit the system.
AI Is Changing React Development Too
In 2026 it is normal to ask an assistant to flag unnecessary client rendering, locate slow page segments, or refactor without behavior changes. Suggestions are not measurements. Without profiling you can beautifully optimize a problem that never existed.
The Real Future of React Performance
The future is not “never use useMemo.” It is an ecosystem where teams spend less energy on tiny render micro-optimizations and more on architecture. The priority ladder looks like:
1. Architecture
↓
2. Server vs Client
↓
3. Data fetching
↓
4. Caching
↓
5. Bundle size
↓
6. Rendering
↓
7. Micro-optimizations
Notice where useMemo sits: near the bottom, where it belongs.
The Rule to Follow in 2026
Write simple React first. Let the compiler take what it can. Measure real performance. Then optimize the actual bottleneck. Avoid components that look like:
useMemo(...)
useCallback(...)
memo(...)
useEffect(...)
useMemo(...)
useCallback(...)
solely because “React needs optimization.” Modern React rewards good architecture over clever code. The best win is often not shaving two milliseconds off a render—it is realizing the component never needed to run in the browser at all.