Sarath KrishnanMarch 9, 2026
When building modern applications with React, performance becomes critical as your app grows. Slow rendering, unnecessary re-renders, and large bundle sizes can negatively impact user experience.
In this blog, we’ll explore practical React performance optimization techniques, including:
Memoization prevents unnecessary recalculations and re-renders by caching previous results.
React provides:
Wrap functional components to prevent re-rendering if props haven't changed.
const Child = React.memo(({ name }) => {
console.log("Child rendered");
return <p>{name}</p>;
});
Use when:
Used to memorise expensive calculations.
const expensiveValue = useMemo(() => {
return heavyCalculation(data);
}, [data]);
Use when:
Memoizes functions to prevent unnecessary re-creation.
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
Useful when passing functions to memoized child components.
Lazy loading loads components only when needed, reducing initial bundle size.
React provides React.lazy() and Suspense.
const Dashboard = React.lazy(() => import("./Dashboard"));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}
Benefits:
Perfect for:
Code splitting divides your bundle into smaller chunks loaded on demand.
If you’re using:
Code splitting is often built-in.
const Home = React.lazy(() => import("./Home"));
const About = React.lazy(() => import("./About"));
Each route becomes its own JavaScript chunk.
Why it matters:
The React Profiler helps identify performance bottlenecks.
You can use:
Example:
<Profiler id="App" onRender={callback}>
<App />
</Profiler>
The Profiler shows:
This helps you:
Unnecessary re-renders are the #1 performance issue in React apps.
❌ Parent re-renders causing child re-renders
❌ Inline functions inside JSX
❌ Inline object/array creation
❌ Mutating state directly
❌ Wrong key usage in lists
Instead of:
<button onClick={() => handleClick(id)}>Click</button>
Use:
const handleClick = useCallback((id) => {
console.log(id);
}, []);
Bad:
<MyComponent style={{ color: "red" }} />
Better:
const style = useMemo(() => ({ color: "red" }), []);
<MyComponent style={style} />
Wrong:
{items.map((item, index) => (
<li key={index}>{item.name}</li>
))}
Better:
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
Stable keys prevent unnecessary DOM diffing.
Instead of optimizing everything blindly:
Remember:
Premature optimization can make your code harder to maintain.
React is fast by default, but large applications need careful optimization.
By using:
You can significantly improve performance and user experience.
0