JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsperformanceReact Performance Optimization
PrevNext
performance
intermediate
25 min read

React Performance Optimization

context
memo
profiler
react
react-compiler
react-virtual
react-window
re-renders
useCallback
useMemo
virtualization

React performance optimization involves preventing unnecessary re-renders with memoization, virtualizing long lists, splitting context providers, and profiling with React DevTools to identify actual bottlenecks before optimizing.

Key Points

1React.memo

Skips re-rendering a component when its props are shallowly equal. Only beneficial for expensive components that frequently receive unchanged props.

2useMemo and useCallback

useMemo caches computed values, useCallback caches function references. Both prevent unnecessary work when dependencies have not changed.

3List Virtualization

Renders only visible rows plus a buffer instead of the full list. Libraries like react-virtual make 10,000-item lists perform like 20-item lists.

4Context Splitting

Split contexts by update frequency so fast-changing values do not trigger re-renders in components that only consume slow-changing values.

5React Profiler

DevTools Profiler shows which components rendered, why, and for how long. Always measure before optimizing to find actual bottlenecks.

What You'll Learn

  • Apply React.memo, useMemo, and useCallback correctly and know when they add more overhead than they save
  • Implement list virtualization for large datasets using react-virtual or react-window
  • Diagnose unnecessary re-renders using the React DevTools Profiler and Highlight Updates
  • Optimize React context usage by splitting providers and using composition patterns

Deep Dive

React's reconciliation algorithm is fast, but unnecessary re-renders can accumulate and cause noticeable lag in complex applications. The key principle is to measure first, then optimize — premature optimization is the root of all evil, and React is already highly optimized out of the box.

React.memo

By default, when a parent re-renders, all its children re-render too — even if their props have not changed. React.memo wraps a component and skips re-rendering when its props are shallowly equal to the previous props:

JSX
const ExpensiveList = React.memo(({ items }) => {
  return items.map(item => <ExpensiveItem key={item.id} item={item} />);
});

Be cautious: React.memo adds overhead for the shallow comparison. Only use it when the component is actually expensive to render and frequently receives the same props. For simple components, the comparison cost can exceed the render cost.

useMemo and useCallback

useMemo memoizes the result of a computation, recalculating only when dependencies change. useCallback memoizes a function reference, preventing it from being recreated on every render. Both are primarily useful when passing values or callbacks to memoized child components:

JSX
const sortedItems = useMemo(() => 
  items.sort((a, b) => a.name.localeCompare(b.name)), 
  [items]
);
const handleClick = useCallback((id) => setSelected(id), []);

Without useCallback, a new function reference is created every render, defeating React.memo on the child. Without useMemo, expensive computations repeat unnecessarily. However, using these hooks everywhere adds complexity and memory overhead for the cached values — only apply them where profiling shows a real benefit.

List Virtualization

Rendering thousands of DOM nodes (e.g., a 10,000-row table) is slow regardless of React optimizations. Virtualization renders only the visible rows plus a small buffer, drastically reducing DOM nodes. Libraries like @tanstack/react-virtual, react-window, and react-virtuoso implement this pattern. A virtualized list of 10,000 items renders as fast as one with 20 items because only ~20 DOM nodes exist at any time.

Context Optimization

When a context value changes, every component consuming that context re-renders. This becomes a problem when a single context holds many values that change at different frequencies. The solution is to split contexts by update frequency: fast-changing values (mouse position, form input) in one context, slow-changing values (user settings, theme) in another. Alternatively, use useSyncExternalStore or state management libraries (Zustand, Jotai) that support fine-grained subscriptions.

React Profiler

The React DevTools Profiler records component renders and shows exactly which components rendered, why they rendered, and how long each render took. The Highlight Updates feature visually outlines components as they re-render, making unnecessary renders immediately visible. Always profile before optimizing — the bottleneck is rarely where you expect.

React Compiler

React Compiler (previously React Forget) is an experimental build-time tool that automatically inserts memoization. It analyzes your components and adds useMemo, useCallback, and React.memo equivalents where beneficial, eliminating the need to manually optimize most re-render patterns. When mature, it will make manual memoization largely unnecessary.

Key Patterns

Move state down — keep state as close to where it is used as possible, so updates only re-render the relevant subtree. Lift content up — pass children as props to avoid re-rendering static content when parent state changes. Use composition over context for passing data through component trees.

Key Interview Distinction

React.memo prevents re-renders when props have not changed. useMemo caches computed values. useCallback caches function references. Virtualization reduces DOM nodes. Context splitting prevents unrelated re-renders. The React Profiler identifies which of these optimizations is actually needed — always measure before optimizing.

Fun Fact

React's virtual DOM diffing was revolutionary when introduced in 2013, but the React team has since said that the virtual DOM is more of an implementation detail than a feature. The real innovation was the declarative component model — the virtual DOM was just an efficient way to make it work. React Compiler takes this further by optimizing at build time.

Learn These First

Debouncing & Throttling

intermediate

Continue Learning

Rendering Strategies & Critical Rendering Path

advanced

Runtime Performance & Profiling

advanced

Memory Leaks & Management

advanced

Practice What You Learned

What are common React performance optimization techniques?
mid
react
Optimize React apps by: preventing unnecessary re-renders (memo, useMemo, useCallback), virtualizing long lists, code splitting routes/components, optimizing context usage, and using proper keys. Measure first with React DevTools Profiler.
Previous
Debouncing & Throttling
Next
Rendering Strategies & Critical Rendering Path
PrevNext