5 React Performance Tips You Should Know in 2026
React applications can become slow if not optimized properly. Here are five actionable tips to keep your React apps fast and responsive.
1. Use React.memo for Expensive Components
React.memo is a higher-order component that prevents unnecessary re-renders by memoizing the component output.
const ExpensiveComponent = React.memo(({ data }) => {
// Complex rendering logic here
return <div>{data.map(item => <Item key={item.id} {...item} />)}</div>;
});
When to use:
- Components that render often with the same props
- Components with expensive render logic
- List items in large lists
When NOT to use:
- Components that always receive different props
- Simple components with minimal render cost
2. Optimize useEffect Dependencies
Incorrect dependencies in useEffect can cause unnecessary re-renders or infinite loops.
// ❌ Bad - runs on every render
useEffect(() => {
fetchData();
});
// ✅ Good - runs only when id changes
useEffect(() => {
fetchData(id);
}, [id]);
// ✅ Even better - memoize the callback
const fetchData = useCallback((id) => {
// fetch logic
}, []);
useEffect(() => {
fetchData(id);
}, [id, fetchData]);
Pro tip: Enable ESLint’s exhaustive-deps rule to catch missing dependencies.
3. Lazy Load Components with React.lazy
Don’t load all components upfront. Use code splitting to load components only when needed.
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
}
Best for:
- Route-based components
- Modal dialogs
- Tabs or accordion content
- Admin panels or dashboard widgets
4. Use useMemo for Expensive Calculations
Memoize expensive computations to avoid recalculating on every render.
const filteredData = useMemo(() => {
return data
.filter(item => item.active)
.sort((a, b) => b.score - a.score)
.slice(0, 100);
}, [data]);
Rule of thumb: Only use useMemo if the calculation is genuinely expensive. Don’t over-optimize!
5. Virtualize Long Lists
For lists with hundreds or thousands of items, render only what’s visible on screen.
import { FixedSizeList } from 'react-window';
function VirtualList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
)}
</FixedSizeList>
);
}
Libraries to consider:
react-window- Lightweight and fastreact-virtual- More flexible, works with TanStack@tanstack/react-virtual- Modern alternative
Bonus: Use the React DevTools Profiler
Always measure before optimizing! The React DevTools Profiler shows you which components are rendering and how long they take.
How to use:
- Install React DevTools browser extension
- Open DevTools → Profiler tab
- Click “Record” → interact with your app → Stop
- Analyze the flame graph to find performance bottlenecks
Summary
- Use
React.memofor expensive components - Optimize
useEffectdependencies - Lazy load components with
React.lazy - Use
useMemofor expensive calculations - Virtualize long lists
- Always measure with React DevTools Profiler
Remember: Don’t optimize prematurely. Profile first, then optimize where it matters most!