Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Performance Optimization
Your Progress0%
0 of 42 completed

React Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App

Performance Optimization

Making React applications fast

React is fast by default, but as your application grows, performance becomes important. Unnecessary re-renders, large bundle sizes, and unoptimized code can slow things down. In this lesson, you'll learn how to identify and fix performance bottlenecks using React.memo, lazy loading, code splitting, and other optimization techniques. Let's make your React apps blazing fast! ⚡

When to Optimize

Premature Optimization Warning:

"Premature optimization is the root of all evil" - Donald Knuth

Don't optimize until you have a problem!

The right approach:
1. Build your app normally
2. Measure performance (React DevTools Profiler)
3. Find actual bottlenecks
4. Then optimize those specific areas

Optimization adds complexity - only do it when needed!

Signs You Need to Optimize

  • Slow interactions (typing, clicking)
  • Laggy scrolling
  • Slow page loads
  • High CPU usage in dev tools
  • Many unnecessary re-renders
  • Large bundle size (slow initial load)

React.memo - Preventing Re-renders

React.memo prevents components from re-rendering when props haven't changed:

The Problem: Unnecessary Re-renders

problem-rerenders.jsx
function Parent() {
  const [count, setCount] = React.useState(0)
  const [name, setName] = React.useState('Alice')
  
  return (
    <div>
      <input value={name} onChange={e => setName(e.target.value)} />
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
      
      {/* ❌ Problem: ExpensiveChild re-renders when name changes */}
      <ExpensiveChild count={count} />
    </div>
  )
}

function ExpensiveChild({ count }) {
  console.log('ExpensiveChild rendered')
  
  // Expensive calculation
  const result = expensiveCalculation(count)
  
  return <div>Result: {result}</div>
}

// When you type in input:
// 1. name changes
// 2. Parent re-renders
// 3. ExpensiveChild re-renders (even though count didn't change!)
// 4. Expensive calculation runs again (wasteful!)

The Solution: React.memo

solution-memo.jsx
function Parent() {
  const [count, setCount] = React.useState(0)
  const [name, setName] = React.useState('Alice')
  
  return (
    <div>
      <input value={name} onChange={e => setName(e.target.value)} />
      <button onClick={() => setCount(count + 1)}>Count: {count}</button>
      
      {/* ✅ Solution: MemoizedChild only re-renders when count changes */}
      <MemoizedChild count={count} />
    </div>
  )
}

// Wrap component in React.memo
const MemoizedChild = React.memo(function ExpensiveChild({ count }) {
  console.log('ExpensiveChild rendered')
  
  const result = expensiveCalculation(count)
  
  return <div>Result: {result}</div>
})

// Now when you type:
// 1. name changes
// 2. Parent re-renders
// 3. React.memo checks: did props change?
// 4. count is same → skip re-render!
// 5. Expensive calculation not run (fast!)

React.memo with Custom Comparison

memo-custom.jsx
// Default: Shallow comparison of props
const MemoizedComponent = React.memo(Component)

// Custom comparison function
const MemoizedComponent = React.memo(Component, (prevProps, nextProps) => {
  // Return true if props are equal (skip re-render)
  // Return false if props changed (do re-render)
  
  return prevProps.id === nextProps.id && 
         prevProps.name === nextProps.name
})

// Example: Only re-render if user ID changes
const UserProfile = React.memo(
  function UserProfile({ user, theme }) {
    return (
      <div>
        <h1>{user.name}</h1>
        <p>{user.email}</p>
      </div>
    )
  },
  (prevProps, nextProps) => {
    // Only compare user.id, ignore theme changes
    return prevProps.user.id === nextProps.user.id
  }
)

// ⚠️ Careful: Custom comparison can be expensive too!
// Only use when default comparison isn't enough

When to Use React.memo:

  • DO use when:
  • • Component renders often with same props
  • • Component is expensive to render
  • • Component is in a list
  • • Profiler shows unnecessary re-renders
  • DON'T use when:
  • • Props change frequently
  • • Component is simple/fast
  • • No performance issue exists

Lazy Loading and Code Splitting

Load components only when needed, reducing initial bundle size:

Basic Lazy Loading

lazy-basic.jsx
import React, { Suspense, lazy } from 'react'

// ❌ Regular import - Loaded immediately
import Dashboard from './Dashboard'

// ✅ Lazy import - Loaded only when needed
const Dashboard = lazy(() => import('./Dashboard'))

function App() {
  const [showDashboard, setShowDashboard] = React.useState(false)
  
  return (
    <div>
      <button onClick={() => setShowDashboard(true)}>
        Show Dashboard
      </button>
      
      {showDashboard && (
        <Suspense fallback={<div>Loading...</div>}>
          <Dashboard />
        </Suspense>
      )}
    </div>
  )
}

// How it works:
// 1. Dashboard code not in initial bundle
// 2. User clicks button
// 3. Dashboard code downloaded
// 4. Loading... shown while downloading
// 5. Dashboard rendered when ready

// Benefits:
// ✅ Smaller initial bundle
// ✅ Faster initial load
// ✅ Better user experience

Lazy Loading Routes

lazy-routes.jsx
import { lazy, Suspense } from 'react'
import { BrowserRouter, Routes, Route } from 'react-router-dom'

// Lazy load page components
const Home = lazy(() => import('./pages/HomePage'))
const About = lazy(() => import('./pages/AboutPage'))
const Dashboard = lazy(() => import('./pages/DashboardPage'))
const Profile = lazy(() => import('./pages/ProfilePage'))

// Loading component
function LoadingSpinner() {
  return (
    <div className="loading">
      <div className="spinner"></div>
      <p>Loading...</p>
    </div>
  )
}

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<LoadingSpinner />}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/profile" element={<Profile />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  )
}

// Each route is a separate chunk
// Only loads when user navigates to it!

// Bundle results:
// main.js - Core app (small)
// home.js - Home page
// about.js - About page
// dashboard.js - Dashboard page
// profile.js - Profile page

Named Exports with Lazy

lazy-named.jsx
// Component file with named export
// UserProfile.jsx
export function UserProfile({ userId }) {
  return <div>User {userId}</div>
}

// ❌ Won't work - lazy needs default export
const UserProfile = lazy(() => import('./UserProfile'))

// ✅ Solution 1: Change to default export
// UserProfile.jsx
export default function UserProfile({ userId }) {
  return <div>User {userId}</div>
}

// ✅ Solution 2: Create wrapper with default export
const UserProfile = lazy(() => 
  import('./UserProfile').then(module => ({
    default: module.UserProfile
  }))
)

// ✅ Solution 3: Re-export as default
// UserProfile.jsx
export function UserProfile({ userId }) {
  return <div>User {userId}</div>
}
export { UserProfile as default }

// Lazy loading requires default exports!

Interactive Demo

ReactPlayground.jsx
Code Editor
Preview

💡 Tip: Edit the code above and click "Run" to see your changes

Bundle Size Optimization

1. Analyze Bundle Size

analyze-bundle.sh
# Install bundle analyzer
npm install --save-dev webpack-bundle-analyzer

# For Create React App
npm install --save-dev cra-bundle-analyzer

# Build and analyze
npm run build
npx cra-bundle-analyzer

# Shows visual representation of bundle contents
# Identify large dependencies to optimize

2. Import Only What You Need

tree-shaking.jsx
// ❌ Bad - Imports entire library
import _ from 'lodash'
const result = _.debounce(fn, 300)

// ✅ Good - Imports only debounce
import debounce from 'lodash/debounce'
const result = debounce(fn, 300)

// ❌ Bad - Imports all icons
import * as Icons from 'react-icons/fa'
<Icons.FaUser />

// ✅ Good - Imports specific icon
import { FaUser } from 'react-icons/fa'
<FaUser />

// ❌ Bad - Imports entire Material-UI
import { Button, TextField, Modal } from '@mui/material'

// ✅ Good - Direct imports
import Button from '@mui/material/Button'
import TextField from '@mui/material/TextField'
import Modal from '@mui/material/Modal'

// Tree-shaking removes unused code
// Only works with ES6 imports!

3. Remove Unused Dependencies

remove-unused.sh
# Find unused dependencies
npx depcheck

# Remove unused packages
npm uninstall unused-package

# Check for duplicate dependencies
npm dedupe

# Regularly audit dependencies
npm audit

Optimizing Lists

Always Use Keys

list-keys.jsx
// ❌ Bad - No key or index as key
users.map(user => <UserCard user={user} />)
users.map((user, index) => <UserCard key={index} user={user} />)

// ✅ Good - Unique, stable ID as key
users.map(user => <UserCard key={user.id} user={user} />)

// Why keys matter:
// - React uses keys to track items
// - Stable keys = efficient updates
// - Index as key = bad performance on reorder/filter

Virtual Scrolling for Large Lists

virtual-scroll.jsx
// For lists with 1000+ items, use virtualization
// Library: react-window or react-virtualized

import { FixedSizeList } from 'react-window'

function LargeList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].name}
    </div>
  )
  
  return (
    <FixedSizeList
      height={600}
      itemCount={items.length}
      itemSize={50}
      width="100%"
    >
      {Row}
    </FixedSizeList>
  )
}

// Only renders visible items!
// Handles 10,000+ items smoothly

Profiling React Apps

React DevTools Profiler

profiler-steps.txt
Steps to profile:
1. Install React DevTools browser extension
2. Open DevTools → Profiler tab
3. Click record button (circle)
4. Interact with your app
5. Click stop button
6. Analyze results:
   - Flame graph shows component hierarchy
   - Ranked chart shows slowest components
   - Click components to see render details

What to look for:
- Components that render frequently
- Long render times
- Unnecessary re-renders
- Large component trees

Color coding:
- Gray: Did not render
- Green: Fast render
- Yellow: Medium render
- Red: Slow render (optimize these!)

Programmatic Profiling

profiler-api.jsx
import { Profiler } from 'react'

function onRenderCallback(
  id,                 // Component identifier
  phase,              // "mount" or "update"
  actualDuration,     // Time to render
  baseDuration,       // Estimated time without memoization
  startTime,          // When render started
  commitTime,         // When render committed
  interactions        // Set of interactions
) {
  console.log(`${id} took ${actualDuration}ms to render`)
  
  // Send to analytics
  if (actualDuration > 100) {
    analytics.track('slow-render', {
      component: id,
      duration: actualDuration
    })
  }
}

function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <Dashboard />
      <Sidebar />
      <Content />
    </Profiler>
  )
}

// Wrap components to measure performance
// Production-safe, minimal overhead

Performance Optimization Checklist

Before Optimizing:

  • ✓ Profile with React DevTools
  • ✓ Identify actual bottlenecks
  • ✓ Measure current performance
  • ✓ Set target metrics

Component Optimization:

  • ✓ Use React.memo for expensive components
  • ✓ Use useMemo for expensive calculations
  • ✓ Use useCallback for callback props
  • ✓ Avoid inline objects/functions in JSX
  • ✓ Split large components into smaller ones

Bundle Optimization:

  • ✓ Lazy load routes
  • ✓ Code split large features
  • ✓ Tree-shake unused code
  • ✓ Analyze bundle size
  • ✓ Remove unused dependencies

List Optimization:

  • ✓ Use stable keys
  • ✓ Virtualize long lists
  • ✓ Paginate large datasets
  • ✓ Debounce search/filter

After Optimizing:

  • ✓ Measure improvement
  • ✓ Profile again
  • ✓ Test in production build
  • ✓ Monitor in production

Key Takeaways

  • Don't optimize prematurely - measure first!
  • Use React DevTools Profiler to find bottlenecks
  • React.memo prevents unnecessary re-renders
  • Lazy loading reduces initial bundle size
  • Code splitting loads components on demand
  • Suspense shows fallback while loading
  • Import only what you need for tree-shaking
  • Use stable keys for lists
  • Virtualize lists with 1000+ items
  • Combine with useMemo and useCallback
  • Analyze bundle size regularly
  • Remove unused dependencies
  • Test performance in production build

What's Next?

You now know how to optimize React applications for performance! You understand React.memo, lazy loading, code splitting, and profiling.

In the next lesson, you'll learn about Error Handling:

  • Error boundaries for catching errors
  • Graceful error handling strategies
  • Error recovery patterns
  • Logging and monitoring errors
  • User-friendly error messages

Get ready to build robust React applications that handle errors gracefully! 🛡️

Learning how to optimize React applications with React.memo, lazy loading, and performance best practices!

Previous
Component Organization
Next
Error Handling

Never Miss a New React Tutorial

Join 2,000+ developers learning React step-by-step. Get new tutorials, tips, and exclusive resources delivered to your inbox - completely FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

React Tutorials

0 of 42 completed

Your Progress0%

Topics

Getting Started

  • What is React?
  • React vs Vanilla JavaScript
  • Setting Up Your Environment
  • Your First React App

JSX Fundamentals

  • Introduction to JSX
  • JSX Expressions and Variables
  • Conditional Rendering
  • Lists and Keys
  • Styling in JSX

Components Basics

  • Function Components
  • Props
  • Children Prop
  • Props Destructuring
  • Component Composition

State Management

  • Introduction to State
  • useState Hook
  • State Updates and Re-renders
  • Multiple State Variables
  • State Best Practices

Events and Interactivity

  • Handling Events
  • Event Objects
  • Forms in React
  • Form Validation

Side Effects and Data

  • Introduction to useEffect
  • Data Fetching
  • Cleanup Functions
  • Dependency Arrays

Advanced Hooks

  • useRef Hook
  • useContext Hook
  • useMemo Hook
  • useCallback Hook

React Patterns

  • Custom Hooks
  • Higher-Order Components
  • Render Props Pattern

React Router

  • Introduction to React Router
  • Routes and Navigation
  • Dynamic Routes and Parameters

Best Practices

  • Component Organization
  • Performance Optimization
  • Error Handling
  • Testing React Components

Real World Project

  • Building a Complete App
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo