React Performance Optimization Interview Guide
Performance Optimization in React
Section titled “Performance Optimization in React”Performance optimization is the process of improving the speed, responsiveness, and efficiency of a React application by minimizing unnecessary rendering, reducing bundle size, optimizing network requests, and improving memory usage.
Common Causes of Unnecessary Re-renders
Section titled “Common Causes of Unnecessary Re-renders”Common causes include:
- Parent component re-renders
- State updates
- Context value changes
- New object, array, or function references created on every render
- Props changes
<MyComponent data={{ name: "John" }} />Even though the content is the same, a new object is created on every render, causing a re-render.
React Rendering Flow
Section titled “React Rendering Flow”flowchart TD
A[State or Props Change] --> B[Render Phase]
B --> C[Virtual DOM Created]
C --> D[Reconciliation / Diffing]
D --> E[Commit Phase]
E --> F[DOM Updated]
React.memo()
Section titled “React.memo()”React.memo() is a Higher Order Component (HOC) that prevents unnecessary re-renders of functional components when props have not changed.
const User = React.memo(({ name }) => { return <h1>{name}</h1>;});Use case: Expensive UI components.
Why Does a React.memo Component Still Re-render?
Section titled “Why Does a React.memo Component Still Re-render?”React.memo only does a shallow prop comparison. It still re-renders when the parent passes a new object, array, or function reference on every render, even if the value looks the same:
<Child user={{ name: "John" }} />Fix by stabilizing the reference with useMemo:
const user = useMemo(() => ({ name: "John" }), []);
<Child user={user} />React.memo vs useMemo
Section titled “React.memo vs useMemo”| React.memo | useMemo |
|---|---|
| Memoizes component rendering | Memoizes computed values |
| Works on components | Works on calculations |
| Prevents re-render | Prevents recalculation |
const result = useMemo(() => expensiveCalculation(data), [data]);useCallback
Section titled “useCallback”useCallback memoizes a function reference so it stays stable across renders unless its dependencies change. Useful when passing callbacks to memoized child components. See the React useCallback Interview Guide for the stale closure problem, useEffect interaction, and when it can hurt performance.
When to Use useMemo
Section titled “When to Use useMemo”Use useMemo for expensive calculations, filtering/sorting large datasets, and complex transformations. React stores and compares dependencies, so for simple computations the memoization overhead can exceed the benefit. Rule: measure first, optimize later. See the React useMemo Interview Guide for dependency-array behavior, the React.memo interaction, and why cached values aren’t guaranteed to persist.
Reconciliation and Performance
Section titled “Reconciliation and Performance”Reconciliation compares Virtual DOM trees and updates only changed elements.
Benefits:
- Minimal DOM updates
- Faster UI updates
- Better rendering performance
Importance of Keys
Section titled “Importance of Keys”Bad:
users.map((user, index) => <User key={index} />);Good:
users.map((user) => <User key={user.id} />);Using array indexes as keys can cause unnecessary re-renders and incorrect UI updates.
Code Splitting and Lazy Loading
Section titled “Code Splitting and Lazy Loading”Breaking the application bundle into smaller chunks loaded on demand reduces initial load time and bundle size. See the React Code Splitting Interview Guide for React.lazy/Suspense usage, route-based splitting, dynamic imports, and the internal chunk-loading flow.
Bundle Size Optimization
Section titled “Bundle Size Optimization”- Code splitting
- Tree shaking
- Lazy loading
- Remove unused dependencies
- Dynamic imports
- Production builds
npm run buildVirtualization
Section titled “Virtualization”Render only visible items instead of the full list.
Without virtualization:
- 100000 rows rendered
With virtualization:
- ~20 visible rows rendered
Popular libraries:
- react-window
- react-virtualized
Optimizing Large Tables
Section titled “Optimizing Large Tables”For datasets with 100k+ records:
- Pagination
- Virtualization
- Server-side filtering
- Server-side sorting
- Memoization
- Infinite scrolling
Pure Components
Section titled “Pure Components”class User extends React.PureComponent {}Functional equivalent:
React.memo(User);Detecting Performance Issues
Section titled “Detecting Performance Issues”Tools:
- React DevTools Profiler
- Chrome Performance Tab
- Lighthouse
- Web Vitals
Metrics:
- Render time
- Commit time
- Component re-renders
- Largest Contentful Paint (LCP)
Context API Performance
Section titled “Context API Performance”Whenever a context value changes, all consumers re-render.
<UserContext.Provider value={user}>Optimization:
const value = useMemo(() => ({ user }), [user]);Also consider splitting contexts. See the React Context API Interview Guide for a full explanation of why context re-renders happen and why React.memo cannot prevent them.
Optimizing API Calls
Section titled “Optimizing API Calls”- Debouncing
- Throttling
- Caching
- Pagination
- Request cancellation
const debouncedSearch = debounce(searchApi, 500);Debouncing
Section titled “Debouncing”Executes an action only after the user stops typing.
debounce(searchApi, 500);Use cases:
- Search boxes
- Auto-suggestions
Throttling
Section titled “Throttling”Limits execution to once every fixed interval.
throttle(handleScroll, 200);Use cases:
- Scroll events
- Resize events
React Query Performance Benefits
Section titled “React Query Performance Benefits”Libraries like React Query and SWR replace hand-rolled useEffect data fetching with a caching layer purpose-built for server state:
- Data caching
- Background refetching
- Request deduplication
- Automatic retries
Senior-Level Interview Scenarios
Section titled “Senior-Level Interview Scenarios”Debugging Unexpected Re-renders
Section titled “Debugging Unexpected Re-renders”Approach:
- React DevTools Profiler
- Check object references
- Check callback references
- Apply React.memo
- Use useMemo/useCallback appropriately
- Inspect Context updates
Example scenario: A parent component updates every second (e.g., a clock tick), but a child’s data never changes. Prevent the child from re-rendering by wrapping it in React.memo and stabilizing the prop reference it receives with useMemo:
const Child = React.memo(({ user }) => { return <div>{user.name}</div>;});
const user = useMemo(() => ({ name: "Abirami"}), []);Optimizing a Dashboard
Section titled “Optimizing a Dashboard”Strategies:
- Parallel API calls with
Promise.all - Lazy-load widgets
- React.memo for widgets
- useMemo for expensive computations
- Cache API responses
- Virtualization for large grids
- Suspense and code splitting
Scaling for Millions of Users
Section titled “Scaling for Millions of Users”- SSR with Next.js
- CDN caching
- Image optimization
- Tree shaking
- Lazy loading
- Bundle analysis
- Virtual scrolling
- Service Workers
- API caching
- Web Vitals monitoring
Performance-Oriented Rendering Lifecycle
Section titled “Performance-Oriented Rendering Lifecycle”- State/Props change
- Render phase
- Reconciliation
- Diffing algorithm
- Commit phase
- DOM update
Goal:
- Reduce renders
- Reduce diffing
- Reduce DOM updates
Diagnosing a Slow React Application
Section titled “Diagnosing a Slow React Application”- Profile the application
- Identify expensive renders
- Analyze network calls
- Inspect bundle size
- Add memoization where beneficial
- Introduce lazy loading
- Virtualize large lists
- Measure again
Key Interview Focus Areas
Section titled “Key Interview Focus Areas”Senior interviews commonly emphasize:
- Why a page is re-rendering
- Slow search optimization
- Dashboard performance tuning
- Large bundle analysis
- Context API performance issues
- React.memo vs useMemo vs useCallback
- Virtual DOM vs Real DOM performance
Summary
Section titled “Summary”- Prevent unnecessary renders with
React.memo,useMemo, anduseCallbackwhen appropriate. - Optimize loading using code splitting, lazy loading, and tree shaking.
- Use virtualization for large datasets and pagination for scalability.
- Profile before optimizing and validate improvements with React DevTools.
- Senior interviews focus on real-world performance debugging rather than memorized definitions.