React
Performance
JavaScript
Frontend
Best Practices
Ask anything about this article
Hi! I've read this article.
What would you like to know?
@farhan
A slow React app is a bad user experience. After optimizing dozens of production React applications, here are the 15 techniques that have the biggest impact.
tsxconst ExpensiveComponent = React.memo(({ data }) => {
// Only re-renders if 'data' prop actually changes
return <div>{/* complex rendering */}</div>;
});
tsxfunction Dashboard({ items }) {
const sortedItems = useMemo(() => {
return [...items].sort((a, b) => b.value - a.value);
}, [items]); // Only recalculates when items changes
return <ItemList items={sortedItems} />;
}
tsxfunction Parent() {
const handleClick = useCallback((id: string) => {
// handle click
}, []); // Stable reference across renders
return <ChildComponent onClick={handleClick} />;
}
tsxconst HeavyChart = React.lazy(() => import('./HeavyChart'));
function Dashboard() {
return (
<Suspense fallback={<LoadingSpinner />}>
<HeavyChart />
</Suspense>
);
}
tsximport { FixedSizeList } from 'react-window';
function UserList({ users }) {
return (
<FixedSizeList
height={600}
itemCount={users.length}
itemSize={50}
>
{({ index, style }) => (
<div style={style}>{users[index].name}</div>
)}
</FixedSizeList>
);
}
tsxfunction SearchBar() {
const [query, setQuery] = useState('');
const debouncedSearch = useMemo(
() => debounce((q: string) => fetchResults(q), 300),
[]
);
return (
<input
value={query}
onChange={(e) => {
setQuery(e.target.value);
debouncedSearch(e.target.value);
}}
/>
);
}
tsx// Use Next.js Image component
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero"
width={800}
height={400}
priority // For above-the-fold images
placeholder="blur"
/>
tsx// ❌ Creates new object every render
<Component style={{ color: 'red' }} />
// ✅ Stable reference
const styles = { color: 'red' };
<Component style={styles} />
tsx// ❌ Index as key causes bugs with reordering
{items.map((item, index) => <Item key={index} />)}
// ✅ Unique, stable ID
{items.map(item => <Item key={item.id} />)}
Move state as close to where it's used as possible:
tsx// ❌ State in parent causes unnecessary re-renders
function App() {
const [inputValue, setInputValue] = useState('');
return (
<>
<Input value={inputValue} onChange={setInputValue} />
<ExpensiveTree /> {/* Re-renders on every keystroke! */}
</>
);
}
// ✅ State colocated in the input component
function App() {
return (
<>
<SearchInput /> {/* Manages its own state */}
<ExpensiveTree /> {/* Doesn't re-render */}
</>
);
}
Use React DevTools Profiler to find performance bottlenecks:
These techniques will transform your React app from sluggish to snappy.