Most slow React apps share the same hidden issues — and none of them are React itself.
When a React app starts feeling sluggish, the first instinct is to blame React. Spoiler: it's almost never React.
🧠 React is not slow by default
React is actually very fast at what it does:
- It batches updates
- It uses a virtual DOM
- It only touches the real DOM when necessary
So if your app feels slow, React is usually just doing extra work because we told it to.
⚠️ The real reason apps feel slow
Most performance issues come from unnecessary re-renders and heavy work inside renders.
Let's break down the common causes.
🔁 1. Unnecessary re-renders
Every time state changes, React re-runs components — even ones that don't depend on that state.
function App() {
const [count, setCount] = React.useState(0);
return (
<div>
<Header /> {/* re-renders even though it doesn't use count */}
<HeavyComponent /> {/* same here */}
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
👉 This becomes expensive as components grow.
🧮 2. Expensive calculations inside render
function App({ items }) {
const sortedItems = items.sort((a, b) => b - a); // runs on EVERY render
return <List items={sortedItems} />;
}
Sorting runs on every render — even if items didn't change. This slows down your app silently.
🔄 3. Creating new objects/functions every render
{/* New function reference created on every render */}
<Child onClick={() => doSomething()} />
{/* New object reference created on every render */}
<Child style={{ color: "red" }} />
React sees these as new props every time, causing unnecessary child re-renders.
🧱 4. Render chain reactions
If a parent updates, children often re-render too — unless you've optimized them. This creates a cascade that's hard to debug.
📍 5. Poor state placement
function App() {
const [theme, setTheme] = useState("dark");
return (
<div>
<Header theme={theme} />
<Dashboard /> {/* doesn't care about theme */}
<Settings /> {/* doesn't care about theme */}
</div>
);
}
Every theme change re-renders the entire app — including components that don't need it.
🚀 So is React the problem?
No.
React is just following your instructions. Most performance issues come from:
- Poor state placement
- Unnecessary work in render
- Missing memoization
- Creating new references on every render
⚡ How to actually fix it
1. Keep state local
Don't lift state unless you absolutely have to. Local state = local re-renders.
2. Use React.memo for heavy components
const HeavyComponent = React.memo(function HeavyComponent() {
return <div>Heavy UI</div>;
});
Skips re-rendering when props haven't changed.
3. Memoize expensive calculations with useMemo
const sortedItems = React.useMemo(() => {
return items.sort((a, b) => b - a);
}, [items]);
Now the sort only runs when items actually changes.
4. Stabilize functions with useCallback
const handleClick = React.useCallback(() => {
doSomething();
}, []);
Preserves the function reference across renders so children don't update unnecessarily.
5. Keep render pure
Render should output only UI. Not:
- ❌ Sorting
- ❌ Filtering
- ❌ Heavy computation
- ❌ API data transformation
🧠 The mental model that helps
Think of React like this:
UI = f(state + props)
React is a calculator. If it feels slow, it's not the calculator — it's the complexity of what you're asking it to calculate.
✅ Before you profile, ask yourself
- Am I re-rendering components that don't need to update?
- Am I doing heavy work inside render?
- Is my state placed too high in the tree?
- Am I creating new object or function references on every render?
Fix these, and your React app will feel extremely fast.
🎯 Final thoughts
The difference between writing React code and writing efficient UI systems is understanding exactly this.
Once you do — things get fun.
Found this useful? Drop a ❤️ and share it with someone still blaming React for their slow app.
Top comments (0)