React is fast, but that doesn’t mean your app always will be.
If you're building modern web apps with React, performance issues can sneak in as your app grows. In this post, we’ll break down common React performance problems, and show you how to fix them with easy-to-apply techniques.
🧠 Why react performance matters
React re-renders components when state or props change. That’s great for reactivity, but it can lead to:
- Slow UI updates
- Laggy interactions
- Unnecessary re-renders
- Memory leaks in large trees
👉 The key is not just building, but building efficiently.
🔍 1. Avoid unnecessary re-renders
💥 Problem:
React re-renders everything in a component tree—even if some components didn’t change.
✅ Solution:
Use React.memo
to memoize functional components:
const UserCard = React.memo(({ user }) => {
return <div>{user.name}</div>;
});
This prevents re-renders unless props actually change.
⚙️ 2. Use usememo
and usecallback
🧠 Usememo
:
Memoizes expensive calculations so they don't run on every render.
const sortedList = useMemo(() => {
return list.sort(sortFunction);
}, [list]);
🧠 Usecallback
:
Memoizes functions, avoiding re-creating them unnecessarily (especially useful when passing props).
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
🧩 3. Split your code (code splitting)
Load only what the user needs. Don't ship your entire app in one bundle.
✅ Use dynamic imports:
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
<Suspense fallback={<Spinner />}>
<HeavyComponent />
</Suspense>
🔧 This makes your app faster by reducing initial load time.
🕵️ 4. Profile and measure first
Don't guess—measure.
Use:
- 🧪 React DevTools Profiler to find slow components
- 🧠 Lighthouse for overall performance audits
- 🧭 Chrome Performance Tab for deep dives
Only optimize what’s actually slow.
🔃 5. Virtualize long lists
Rendering hundreds of DOM nodes? That’s expensive.
✅ Use libraries like:
react-window
react-virtualized
import { FixedSizeList as List } from 'react-window';
<List height={300} itemCount={1000} itemSize={35} width={300}>
{({ index, style }) => <div style={style}>Item {index}</div>}
</List>
This renders only visible items, saving memory and CPU.
💡 6. Optimize images and assets
- Use modern image formats (WebP, AVIF)
- Compress assets
- Lazy-load images (
loading="lazy"
in<img>
) - Use a CDN for delivery
These don’t relate to React directly, but hugely impact perceived performance.
🧪 7. Avoid anonymous functions in JSX
❌ This causes re-renders:
<MyComponent onClick={() => doSomething()} />
✅ Instead, define with usecallback
or pass references:
const handleClick = useCallback(() => doSomething(), []);
<MyComponent onClick={handleClick} />
⚠️ 8. Be careful with context
React Context is powerful, but every change triggers a full re-render of all consuming components.
Use context only for:
- Auth/session
- Theme
- Localization
For frequent updates (like form state or data), use other tools like:
Zustand
Redux
Jotai
- Component-level state
✅ Summary checklist
- ✅ Use
React.memo
,useMemo
,useCallback
- ✅ Use code-splitting and lazy loading
- ✅ Profile before optimizing
- ✅ Virtualize long lists
- ✅ Optimize images and avoid large bundles
- ✅ Avoid anonymous functions in render
- ✅ Use Context wisely
🧠 Final thoughts
React makes building interfaces easier, but performance requires intention. With a few smart optimizations, you can dramatically improve your app's speed and responsiveness.
Start small, measure often, and remember: fast feels good