Fine-tuning Performance: Optimization with React.memo and useMemo

Learn to eliminate wasted renders and sluggish calculations to make your React applications faster and more efficient.

My App

Welcome! Let's explore how to make our React apps faster. Here's an app with a counter and a separate `Header` component.

function App() {
  const [count, setCount] = useState(0);
  return (
    <>
      <Header title="My App" />
      <button>Count: {count}</button>
    </>
  );
}

The Problem: Unnecessary Re-renders

By default, React re-renders a component whenever its parent re-renders, even if the child's props haven't changed. For complex components, this can lead to significant performance issues. The key to optimization is to **prevent re-renders** that are not necessary.

React.memo: Memoizing Components

`React.memo` is a Higher-Order Component (HOC) that wraps your component and prevents it from re-rendering if its props are the same as the last render. It performs a "shallow comparison" of props. Think of it as telling React: "Don't re-render this unless you have to."

useMemo: Memoizing Expensive Values

The `useMemo` hook is for a different problem: expensive calculations inside your component. It memoizes (caches) the *result* of a function. The function will only be re-executed if one of the dependencies in its dependency array has changed. This avoids recalculating complex values on every render.

The Result: A Faster Application

By strategically using `React.memo` for components and `useMemo` for values, you can significantly speed up your application, reduce wasted rendering cycles, and provide a smoother user experience, especially in data-heavy applications.

Practice Zone


Interactive Test 1: Match the Tool

Match the optimization tool to its primary use case.

Arrastra en el orden correspondiente.


Arrastra las opciones:

useMemo(() => findPrime(num), [num])
React.memo(UserProfile)

Completa el código:

Prevents component re-renders______
Avoids expensive calculations______
Unlock with Premium

Interactive Test 2: Complete the Code

Rellena los huecos en cada casilla.

// A component that receives complex data
const DataChart = (({ data }) => {
  console.log("Rendering Chart...");
  return <div>...chart...</div>;
});

function Dashboard({ numbers }) {
  // This calculation is very slow
  const sum = (() => 
    numbers.reduce((acc, val) => acc + val, 0), 
    [numbers]
  );

  return <div>Total: {sum}</div>;
}
Unlock with Premium

Practice Example: Code Editor

You have a `Header` component that re-renders every time a counter in its parent `App` component updates. Fix this by wrapping the `Header` component in `React.memo` so it only re-renders when its own props change.

Enunciado:

Notice how 'Rendering Header...' is only logged once in the console, even when you click the button multiple times. You've successfully prevented unnecessary re-renders!

* Escribe el código a continuación. Los caracteres correctos se mostrarán en verde y los incorrectos en rojo.

import React, { useState } from 'react'; const Header = React.memo(() => { console.log("Rendering Header..."); return <h1>My App</h1>; }); export default function App() { const [count, setCount] = useState(0); return ( <div> <Header /> <button onClick={() => setCount(c => c + 1)}> Count: {count} </button> </div> ); }

Unlock with Premium

Knowledge Check

When should you use the `useMemo` hook?


Unlock with Premium

Optimization in Action

`React.memo` and `useMemo` are powerful, but knowing *when* and *how* to use them with other React features is key to building truly high-performance applications.


1. The `useCallback` Connection

If you pass a function as a prop to a memoized component, `React.memo` will see it as a new prop on every render (because functions are redefined). This breaks the memoization. The solution is to wrap the function prop in `useCallback` to ensure it keeps the same reference between renders.

const MemoizedButton = React.memo(Button);

function App() {
  const handleClick = useCallback(() => {
    // ... do something
  }, []); // Empty array means function is created only once

  return <MemoizedButton onClick={handleClick} />;
}

2. Memoizing Lists of Components

When rendering a long list of items, performance can degrade quickly. Wrapping the list item component in `React.memo` is a common and highly effective optimization technique. This ensures that only the items that actually change are re-rendered.

const ListItem = React.memo(({ item }) => {
  return <li>{item.name}</li>;
});

function MyList({ items }) {
  return <ul>{items.map(i => <ListItem key={i.id} item={i} />)}</ul>;
}

3. When NOT to Optimize

Optimization isn't free—it adds complexity and uses memory. Applying `memo` or `useMemo` everywhere is a bad practice known as **premature optimization**. Only apply these techniques when you have a measurable performance problem. Use the React DevTools Profiler to identify components that are re-rendering too often or calculations that are genuinely slow.


Practical Takeaway: Profile first, then optimize. Use `React.memo` for components and `useMemo`/`useCallback` for props to fix identified bottlenecks and keep your application fast and responsive.

Optimization Glossary

Memoization
An optimization technique that involves caching the results of expensive function calls and returning the cached result when the same inputs occur again.
React.memo
A Higher-Order Component (HOC) that memoizes a rendered component. React will skip re-rendering the component if its props have not changed.
useMemo
A React Hook that memoizes the result of a calculation. It re-runs the calculation only when one of its dependencies has changed.
useCallback
A React Hook that returns a memoized version of a callback function. It's useful for passing callbacks to optimized child components that rely on referential equality.
Referential Equality
The concept that two variables refer to the exact same object in memory. In JavaScript, non-primitive types like objects, arrays, and functions are compared by reference, not by value. `useMemo` and `useCallback` help preserve referential equality between renders.