Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
LoginSign Up
menu
  1. Home
  2. /Web Development
  3. /React
  4. /Usememo Hook
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

useMemo Hook

Optimizing performance with memoization

React components re-render frequently, and every time they do, all code inside runs again. If you have expensive calculations (complex math, data processing, filtering large lists), they'll run on every render - even if their inputs haven't changed! The useMemo hook solves this by memoizing (caching) calculation results, recomputing only when necessary. Let's learn how to optimize your React apps! ⚡

The Problem: Expensive Re-computations

Without useMemo, expensive operations run on every render:

problem-without-memo.jsx
function ProductList({ products }) {
  const [sortOrder, setSortOrder] = React.useState('asc')
  const [filterText, setFilterText] = React.useState('')
  
  // ❌ Problem: This runs on EVERY render!
  const expensiveCalculation = () => {
    console.log('Computing expensive result...')
    let result = 0
    for (let i = 0; i < 1000000000; i++) {
      result += i
    }
    return result
  }
  
  const expensive = expensiveCalculation()  // Runs every render!
  
  return (
    <div>
      <p>Result: {expensive}</p>
      <input 
        value={filterText} 
        onChange={e => setFilterText(e.target.value)}
        placeholder="Filter..."
      />
      <button onClick={() => setSortOrder('desc')}>Sort</button>
    </div>
  )
}

// Problem:
// 1. User types in input
// 2. filterText changes, component re-renders
// 3. expensiveCalculation runs again (even though result is same!)
// 4. App feels slow and laggy

What is Memoization?

Memoization is caching a function's result based on its inputs.

If the inputs haven't changed, return the cached result instead of recomputing.

It's like remembering the answer to a math problem instead of solving it again!

The Solution: useMemo

useMemo caches the result and only recomputes when dependencies change:

solution-with-memo.jsx
function ProductList({ products }) {
  const [sortOrder, setSortOrder] = React.useState('asc')
  const [filterText, setFilterText] = React.useState('')
  
  // ✅ Solution: Memoize the expensive calculation
  const expensive = React.useMemo(() => {
    console.log('Computing expensive result...')
    let result = 0
    for (let i = 0; i < 1000000000; i++) {
      result += i
    }
    return result
  }, [])  // Empty array = compute once, cache forever
  
  return (
    <div>
      <p>Result: {expensive}</p>
      <input 
        value={filterText} 
        onChange={e => setFilterText(e.target.value)}
        placeholder="Filter..."
      />
      <button onClick={() => setSortOrder('desc')}>Sort</button>
    </div>
  )
}

// How it works:
// 1. First render: Computation runs, result cached
// 2. User types in input, component re-renders
// 3. useMemo returns cached result (no recomputation!)
// 4. App stays fast and responsive

useMemo Syntax

usememo-syntax.jsx
const memoizedValue = React.useMemo(
  () => {
    // Expensive calculation
    return result
  },
  [dependencies]  // Recompute when these change
)

// Parts:
// 1. Callback function - Returns the value to memoize
// 2. Dependency array - When to recompute

// Example with dependencies:
const filtered = React.useMemo(() => {
  return products.filter(p => p.name.includes(searchTerm))
}, [products, searchTerm])  // Recompute when products or searchTerm change

🤔 useMemo vs useEffect

useMemo: Returns a memoized VALUE
const value = useMemo(() => calculation, [deps])

useEffect: Runs side effects, returns nothing (or cleanup)
useEffect(() => { doSideEffect() }, [deps])

Use useMemo for calculations, useEffect for side effects!

Common useMemo Use Cases

1. Filtering Large Lists

use-case-filter.jsx
function ProductList({ products }) {
  const [searchTerm, setSearchTerm] = React.useState('')
  const [category, setCategory] = React.useState('all')
  
  // Memoize filtered products
  const filteredProducts = React.useMemo(() => {
    console.log('Filtering products...')
    
    return products
      .filter(p => 
        p.name.toLowerCase().includes(searchTerm.toLowerCase())
      )
      .filter(p => 
        category === 'all' || p.category === category
      )
  }, [products, searchTerm, category])
  
  return (
    <div>
      <input 
        value={searchTerm}
        onChange={e => setSearchTerm(e.target.value)}
        placeholder="Search..."
      />
      <select value={category} onChange={e => setCategory(e.target.value)}>
        <option value="all">All</option>
        <option value="electronics">Electronics</option>
        <option value="clothing">Clothing</option>
      </select>
      
      <ul>
        {filteredProducts.map(p => (
          <li key={p.id}>{p.name}</li>
        ))}
      </ul>
    </div>
  )
}

// Without useMemo: Filters every render (slow for large lists)
// With useMemo: Filters only when products, searchTerm, or category change

2. Sorting Data

use-case-sort.jsx
function UserTable({ users }) {
  const [sortBy, setSortBy] = React.useState('name')
  const [sortOrder, setSortOrder] = React.useState('asc')
  
  // Memoize sorted users
  const sortedUsers = React.useMemo(() => {
    console.log('Sorting users...')
    
    const sorted = [...users].sort((a, b) => {
      if (a[sortBy] < b[sortBy]) return sortOrder === 'asc' ? -1 : 1
      if (a[sortBy] > b[sortBy]) return sortOrder === 'asc' ? 1 : -1
      return 0
    })
    
    return sorted
  }, [users, sortBy, sortOrder])
  
  return (
    <table>
      <thead>
        <tr>
          <th onClick={() => setSortBy('name')}>Name</th>
          <th onClick={() => setSortBy('age')}>Age</th>
          <th onClick={() => setSortBy('email')}>Email</th>
        </tr>
      </thead>
      <tbody>
        {sortedUsers.map(user => (
          <tr key={user.id}>
            <td>{user.name}</td>
            <td>{user.age}</td>
            <td>{user.email}</td>
          </tr>
        ))}
      </tbody>
    </table>
  )
}

3. Complex Calculations

use-case-calculation.jsx
function DataDashboard({ data }) {
  const [showDetails, setShowDetails] = React.useState(false)
  
  // Memoize statistics calculation
  const stats = React.useMemo(() => {
    console.log('Computing statistics...')
    
    return {
      total: data.reduce((sum, item) => sum + item.value, 0),
      average: data.reduce((sum, item) => sum + item.value, 0) / data.length,
      max: Math.max(...data.map(item => item.value)),
      min: Math.min(...data.map(item => item.value)),
      median: calculateMedian(data.map(item => item.value))
    }
  }, [data])  // Only recompute when data changes
  
  return (
    <div>
      <h2>Statistics</h2>
      <p>Total: {stats.total}</p>
      <p>Average: {stats.average}</p>
      <p>Max: {stats.max}</p>
      <p>Min: {stats.min}</p>
      <p>Median: {stats.median}</p>
      
      <button onClick={() => setShowDetails(!showDetails)}>
        Toggle Details
      </button>
      {/* Toggling showDetails doesn't recompute stats! */}
    </div>
  )
}

4. Preventing Reference Changes

use-case-reference.jsx
function Parent() {
  const [count, setCount] = React.useState(0)
  const [name, setName] = React.useState('')
  
  // ❌ Without useMemo: New object every render
  const config = { theme: 'dark', language: 'en' }
  
  // ✅ With useMemo: Same object reference
  const config = React.useMemo(() => ({
    theme: 'dark',
    language: 'en'
  }), [])  // Object recreated only on mount
  
  return <Child config={config} />
}

// Why this matters:
// If Child is wrapped in React.memo, it won't re-render
// unnecessarily when config reference stays the same

When to Use useMemo

✅ DO Use useMemo When:

  • Expensive calculations - Complex math, data processing
  • Filtering/sorting large lists - Arrays with 1000+ items
  • Complex transformations - Mapping, reducing large datasets
  • Preventing reference changes - Objects/arrays passed to React.memo components
  • Measured performance issue - You've profiled and found a bottleneck

❌ DON'T Use useMemo When:

  • Simple calculations - Adding numbers, simple string operations
  • Small lists - Arrays with <100 items
  • No performance problem - Don't optimize prematurely!
  • Everywhere "just in case" - useMemo has overhead too

Premature Optimization Warning:

Don't use useMemo everywhere! It adds complexity and has its own overhead.

Steps to optimize:
1. Write code normally
2. Measure performance (React DevTools Profiler)
3. If you find a real problem, then add useMemo

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

Common useMemo Mistakes

1. Missing Dependencies

mistake-deps.jsx
// ❌ Wrong - Missing searchTerm dependency
const filtered = React.useMemo(() => {
  return products.filter(p => p.name.includes(searchTerm))
}, [products])  // Missing searchTerm!

// Result: Stale data when searchTerm changes

// ✅ Correct - Include all dependencies
const filtered = React.useMemo(() => {
  return products.filter(p => p.name.includes(searchTerm))
}, [products, searchTerm])

2. Overusing useMemo

mistake-overuse.jsx
// ❌ Bad - Overusing for simple operations
function Component({ a, b }) {
  const sum = React.useMemo(() => a + b, [a, b])  // Unnecessary!
  const double = React.useMemo(() => sum * 2, [sum])  // Unnecessary!
  
  return <div>{double}</div>
}

// ✅ Good - No memoization needed
function Component({ a, b }) {
  const sum = a + b  // Fast, no need to memoize
  const double = sum * 2  // Fast, no need to memoize
  
  return <div>{double}</div>
}

// Rule: Only memoize if calculation is actually expensive

3. Memoizing Components Instead of Values

mistake-component.jsx
// ❌ Wrong - useMemo for components
const MyComponent = React.useMemo(() => {
  return <div>Component</div>
}, [])

// ✅ Correct - Use React.memo for components
const MyComponent = React.memo(function MyComponent() {
  return <div>Component</div>
})

// useMemo = for values
// React.memo = for components

4. Complex Dependency Arrays

mistake-complex-deps.jsx
// ❌ Problematic - Object in dependencies
const result = React.useMemo(() => {
  return calculate(config)
}, [config])  // config is object, new reference every render!

// ✅ Better - Destructure or use specific properties
const result = React.useMemo(() => {
  return calculate(config)
}, [config.setting1, config.setting2])

// ✅ Or memoize config too
const config = React.useMemo(() => ({
  setting1: value1,
  setting2: value2
}), [value1, value2])

useMemo Patterns

Pattern 1: Expensive List Operations

pattern-list.jsx
function DataTable({ data, filters }) {
  // Chain memoized operations
  const filtered = React.useMemo(() => {
    return data.filter(item => 
      filters.category === 'all' || item.category === filters.category
    )
  }, [data, filters.category])
  
  const sorted = React.useMemo(() => {
    return [...filtered].sort((a, b) => 
      a[filters.sortBy] > b[filters.sortBy] ? 1 : -1
    )
  }, [filtered, filters.sortBy])
  
  const paginated = React.useMemo(() => {
    const start = (filters.page - 1) * filters.pageSize
    return sorted.slice(start, start + filters.pageSize)
  }, [sorted, filters.page, filters.pageSize])
  
  return (
    <table>
      {paginated.map(item => <Row key={item.id} item={item} />)}
    </table>
  )
}

Pattern 2: Memoized Context Value

pattern-context.jsx
function ThemeProvider({ children }) {
  const [theme, setTheme] = React.useState('light')
  
  // Memoize context value to prevent unnecessary re-renders
  const value = React.useMemo(() => ({
    theme,
    setTheme,
    toggleTheme: () => setTheme(t => t === 'light' ? 'dark' : 'light')
  }), [theme])
  
  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  )
}

Pattern 3: Derived State

pattern-derived.jsx
function ShoppingCart({ items }) {
  // Memoize calculations based on items
  const summary = React.useMemo(() => {
    return {
      subtotal: items.reduce((sum, item) => sum + item.price * item.quantity, 0),
      tax: items.reduce((sum, item) => sum + item.price * item.quantity, 0) * 0.1,
      shipping: items.length > 0 ? 5 : 0,
      get total() { return this.subtotal + this.tax + this.shipping }
    }
  }, [items])
  
  return (
    <div>
      <p>Subtotal: ${summary.subtotal}</p>
      <p>Tax: ${summary.tax}</p>
      <p>Shipping: ${summary.shipping}</p>
      <p>Total: ${summary.total}</p>
    </div>
  )
}

Key Takeaways

  • useMemo caches calculated values
  • Only recomputes when dependencies change
  • Use for expensive calculations and large list operations
  • Helps prevent unnecessary re-computations
  • Returns a memoized VALUE (not a function)
  • Include all dependencies in the array
  • Don't use for simple calculations (overhead not worth it)
  • Measure before optimizing - avoid premature optimization
  • Can memoize objects/arrays to prevent reference changes
  • Useful for optimizing context values
  • Different from useCallback (which memoizes functions)
  • Use React DevTools Profiler to find real bottlenecks
  • Memoization trades memory for speed

What's Next?

You now understand useMemo and how to optimize expensive calculations! You know when to use memoization and when it's unnecessary.

In the next lesson, you'll learn about useCallback Hook:

  • What is useCallback and how it differs from useMemo
  • Memoizing functions to prevent re-renders
  • When to use useCallback vs useMemo
  • Optimizing callback props
  • Common useCallback patterns

Get ready to complete your performance optimization toolkit! 🚀

Learning how to optimize React performance with useMemo memoization!

Previous
useContext Hook
Next
useCallback Hook

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