Performance ⚡
React performance comes from understanding what triggers renders, limiting work via memoization and virtualization, and profiling before optimizing.
1) Rendering Behavior & Triggers 🔁
- State updates inside a component.
- New props from parents.
- Context value changes.
- External store updates (e.g.,
useSyncExternalStore).
🧠 Renders are cheap; DOM mutations are expensive. Focus on cases where renders cascade unnecessarily.
Checklist ✅
- Co-locate state so changes do not ripple across distant components.
- Split large components into smaller ones to scope re-renders.
- Prefer derived data (computed during render) over duplicating state.
2) Memoization Strategies 🧮
Memoization helps when:
- Expensive calculations repeat with identical inputs.
- Props passed to pure child components change reference frequently.
Tools:
React.memo(Component)for memoizing component outputs.useMemofor expensive values.useCallbackfor stable callback references.
❌ Memoization everywhere can hurt due to extra comparisons and memory. Use only when profiling reveals churn.
3) Virtualization 🧱
Render only what’s visible using libraries like react-window or react-virtualized.
import { FixedSizeList as List } from "react-window";
function Messages({ items }) {
return (
<List
height={400}
width={300}
itemCount={items.length}
itemSize={40}
>
{({ index, style }) => (
<div style={style}>{items[index].text}</div>
)}
</List>
);
}- ✅ Reduce DOM nodes.
- ✅ Improve scroll performance.
- ❌ Adds complexity (measurements, dynamic heights).
4) Code Splitting 🧊
Use React.lazy and Suspense to load components on demand.
import { Suspense, lazy } from "react";
const SettingsPage = lazy(() => import("./SettingsPage"));
function App() {
return (
<Suspense fallback={<Spinner />}>
<SettingsPage />
</Suspense>
);
}- Helps initial load; combine with route-level splitting.
- For granular chunks, split by feature modules.
5) Profiling with React DevTools 🧪
- Use the Profiler tab to record interactions.
- Analyze flame charts to see components re-rendering frequently.
- Highlight updates during navigation to spot wasted renders.
Profiler Workflow
- Record interaction (e.g., typing).
- Identify components with high render durations.
- Optimize using memoization or state colocation.
- Re-profile to confirm improvement.
6) Avoiding Unnecessary Renders 🧘
- State colocation: keep state near components that need it.
- Stable props: wrap static callbacks in
useCallback, memoize data objects. - Split contexts: separate frequently changing data from rarely updated data.
- Immutable data: prefer
map,filter,reduceto create new references intentionally.
Key Takeaways ✅
- Understand what triggers renders before optimizing.
- Memoization, virtualization, and code splitting target different bottlenecks.
- Profiling is mandatory; never guess.
- Keep state local and props stable to prevent ripple re-renders.
Recap 🔄
React performance work begins with render awareness, followed by targeted optimizations: memoization for CPU-heavy calculations, virtualization to shrink DOM, code splitting for faster bundles, and DevTools profiling to validate results. Keep state localized and props stable to reduce unnecessary updates.