DevPrep
  • Interview Prep
  • Projects
  • Resources
  • Pricing
  • About Us
Submit Question
DevPrep
  • Pricing
  • About Us
Submit Question
  1. Home
  2. Articles
  3. Frontend Engineering
  4. React Performance Optimization: A Systematic Approach
XLinkedInReddit
MediumFrontend Engineering

React Performance Optimization: A Systematic Approach

D
DevPrep Team
February 10, 2026·2 min read·0
Table of Contents
  • Step 1: Measure
  • Step 2: Identify the Problem
  • Unnecessary Re-renders
  • Expensive Computations
  • Callback Identity
  • Step 3: Apply Targeted Fixes
  • What NOT to Optimize

Don't optimize blindly. Measure first, then apply targeted fixes. Here's the systematic approach we use at Google.

Step 1: Measure

// React DevTools Profiler
// 1. Open React DevTools → Profiler tab
// 2. Click Record
// 3. Interact with your app
// 4. Stop recording
// 5. Look for components with long render times

Step 2: Identify the Problem

Unnecessary Re-renders

// Problem: Parent re-render causes child re-render
function Parent() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>{count}</button>
      <ExpensiveChild /> {/* Re-renders even though it doesn't use count */}
    </div>
  );
}

// Fix: React.memo
const ExpensiveChild = React.memo(function ExpensiveChild() {
  return <div>{/* expensive render */}</div>;
});

Expensive Computations

// Problem: filtering runs on every render
function UserList({ users, query }) {
  const filtered = users.filter(u => u.name.includes(query)); // Runs every render!
  return filtered.map(u => <UserCard key={u.id} user={u} />);
}

// Fix: useMemo
function UserList({ users, query }) {
  const filtered = useMemo(
    () => users.filter(u => u.name.includes(query)),
    [users, query]
  );
  return filtered.map(u => <UserCard key={u.id} user={u} />);
}

Callback Identity

// Problem: new function reference every render breaks memo
function Parent() {
  const handleClick = (id) => deleteItem(id); // New ref every render!
  return <MemoizedList onClick={handleClick} />;
}

// Fix: useCallback
function Parent() {
  const handleClick = useCallback((id) => deleteItem(id), []);
  return <MemoizedList onClick={handleClick} />;
}

Step 3: Apply Targeted Fixes

  • Virtualization: For long lists (1000+ items), use react-window or @tanstack/virtual
  • Code splitting: Lazy load routes and heavy components
  • Debounce inputs: Don't trigger re-renders on every keystroke
  • State colocation: Move state closer to where it's used
  • Context splitting: Split contexts to prevent unnecessary consumer re-renders

What NOT to Optimize

  • Don't memo everything — memo has a cost too
  • Don't optimize before measuring
  • Don't optimize components that render rarely
  • Don't optimize if users aren't experiencing issues

Related Articles

MediumFrontend Engineering

System Design #12: Design a Multi-Step Form Wizard

7 min read
MediumFrontend Engineering

Mastering Senior-Level JavaScript Interview Concepts

2 min read
MediumFrontend Engineering

System Design #9: Design a Collaborative Text Editor

9 min read

Comments (0)

Sign in to leave a comment.

No comments yet. Be the first to comment.

Table of Contents

  • Step 1: Measure
  • Step 2: Identify the Problem
  • Unnecessary Re-renders
  • Expensive Computations
  • Callback Identity
  • Step 3: Apply Targeted Fixes
  • What NOT to Optimize

Series

View all Frontend Engineering articles →

Practice

  • JavaScript
  • DSA
  • Machine Coding
  • System Design

Resources

  • Learning Tracks
  • Articles
  • Roadmaps
  • Compare Concepts
  • Glossary
  • Developer Tools
  • All Questions

Company

  • About
  • Pricing

Legal

  • Privacy Policy
  • Terms of Service
DevPrep

© 2026 DevPrep. All rights reserved.