Loading content…
Loading content…
Master React performance optimization: memo, useMemo, useCallback, virtualization, and profiling with DevTools
useState, useReducer).import React from "react";
interface UserProfileProps {
name: string;
role: string;
}
// Without memo: Re-renders every time the parent renders
// With memo: Only re-renders if name or role changes
export const UserProfile = React.memo(({ name, role }: UserProfileProps) => {
console.log("UserProfile rendered!");
return (
<div className="p-4 border rounded shadow-sm bg-white">
<h3 className="font-bold">{name}</h3>
<p className="text-gray-600">{role}</p>
</div>
);
});
UserProfile.displayName = "UserProfile";
import { useMemo } from "react";
const ProductAnalyzer = ({ items }: { items: number[] }) => {
// Only recalculate the sum when items array changes
const totalSum = useMemo(() => {
console.log("Calculating heavy sum...");
return items.reduce((sum, num) => sum + num, 0);
}, [items]);
return <p>Total sum of items: {totalSum}</p>;
};
import { useState, useCallback } from "react";
import { UserProfile } from "./UserProfile";
export const Dashboard = () => {
const [count, setCount] = useState(0);
// Without useCallback: a new function is created on every render,
// which causes the child (UserProfile) to re-render even with React.memo!
// With useCallback: function reference stays the same.
const handleUserClick = useCallback(() => {
console.log("User profile clicked");
}, []); // Empty dependency array keeps reference stable
return (
<div>
<button onClick={() => setCount((c) => c + 1)}>Clicks: {count}</button>
<UserProfile name="Amit" role="Developer" onClick={handleUserClick} />
</div>
);
};
Common Pitfall
React.memo or every function in useCallback. Memoization has memory and CPU overhead (React must run dependency checks and store cache values). If a component is simple and renders fast, optimization is slower than the render itself..map(), the browser will create 10,000 HTML elements. This blocks the browser's main thread, causing severe lag and scroll stutter.react-window or react-virtuoso rather than writing your own virtualization logic from scratch.import { FixedSizeList as List } from "react-window";
const Row = ({ index, style }: { index: number; style: React.CSSProperties }) => (
<div style={style} className="p-2 border-b bg-white flex items-center">
Row item #{index}
</div>
);
export const MassiveList = () => (
// Only renders ~10 elements in the DOM instead of 5,000!
<List
height={400}
itemCount={5000}
itemSize={40}
width="100%"
>
{Row}
</List>
);
+-------------------------------------------------------------+
| Flamegraph (Top to Bottom tree) |
| [ App: 12ms (Yellow) ] |
| +-- [ Navigation: 0.1ms (Gray) ] |
| +-- [ ListContainer: 10ms (Orange) ] |
| +-- [ ListItem: 0.5ms (Green) ] |
+-------------------------------------------------------------+
Pro Tip
Performance Checklist
React.memo to compare props, useMemo to cache values, and useCallback to cache functions.Marking it complete updates your roadmap progress percentage.