logo

My Blog

logoTutorial by University of Code

Ken's Daily Blog

Welcome to Every Developer's favourite blog in the Devosphere!

New product features | The latest in technology | The weekly debugging nightmares & More!

Ken Tandrian

Unlocking Performance: A Deep Dive into React Memoization

July 12, 2025 at 05:51 PM

Ken Tandrian

Ken Tandrian

Learn how to optimize your React applications by strategically using React.memo, useCallback, and useMemo to prevent unnecessary re-renders and boost performance.

Technology

Boosting React Performance: Memoization Techniques Explained

In the world of React, performance is key. A slow, janky user interface can quickly frustrate users and lead to a poor experience. One of the most common culprits for performance issues in React applications is unnecessary re-renders. When a component re-renders, React re-executes its render function, and if not handled carefully, this can cascade down the component tree, leading to wasted computation.

Fortunately, React provides powerful tools to help us optimize performance by preventing these unnecessary re-renders: React.memo, useCallback, and useMemo. These are all forms of memoization, a technique where a function's return value is cached based on its inputs, and if the same inputs occur again, the cached value is returned instead of re-executing the function.

Understanding Unnecessary Re-renders

Before we dive into the solutions, let's understand the problem. In React, a component re-renders when:

The third point is often the sneaky one that leads to performance bottlenecks. If a parent component re-renders, by default, all its children will also re-render, even if their props haven't actually changed. This is where memoization comes to the rescue.

React.memo: Memoizing Components

React.memo is a higher-order component (HOC) that "memoizes" a functional component. It prevents the component from re-rendering if its props have not changed. Think of it as a pure component for functional components.

When to use it: Use React.memo for "pure" components that:

Example:

component.jsx
1// Before React.memo
2function MyExpensiveComponent({ data }) {
3  // Imagine complex calculations or heavy rendering here
4  console.log('MyExpensiveComponent re-rendered');
5  return <div>{data.map(item => <p key={item.id}>{item.name}</p>)}</div>;
6}
7
8// After React.memo
9import React from 'react';
10
11const MyMemoizedComponent = React.memo(function MyExpensiveComponent({ data }) {
12  console.log('MyMemoizedComponent re-rendered');
13  return <div>{data.map(item => <p key={item.id}>{item.name}</p>)}</div>;
14});
15
16export default MyMemoizedComponent;


Now, MyMemoizedComponent will only re-render if its data prop (or any other props it receives) actually changes.

useCallback: Memoizing Functions

useCallback is a React Hook that memoizes functions. When a component re-renders, any inline functions defined within it are recreated. This means that even if a child component is wrapped in React.memo, if it receives a new function prop on every parent re-render, it will still re-render because the prop technically "changed" (it's a new reference).

When to use it: Use useCallback when:

Example:

component.jsx
1import React, { useState, useCallback } from 'react';
2
3const Button = React.memo(({ onClick, label }) => {
4  console.log(`${label} Button re-rendered`);
5  return <button onClick={onClick}>{label}</button>;
6});
7
8function ParentComponent() {
9  const [count, setCount] = useState(0);
10
11  // Without useCallback, handleIncrement would be a new function on every render,
12  // causing Button to re-render even if it's memoized.
13  // const handleIncrement = () => setCount(count + 1);
14
15  // With useCallback, handleIncrement only changes if count changes
16  const handleIncrement = useCallback(() => {
17    setCount(prevCount => prevCount + 1);
18  }, []); // Empty dependency array means it's created once
19
20  return (
21    <div>
22      <h1>Count: {count}</h1>
23      <Button onClick={handleIncrement} label="Increment" />
24      <button onClick={() => setCount(0)}>
25        Reset Count (Causes re-render of Button if not memoized)
26      </button>
27    </div>
28  );
29}
30
31export default ParentComponent;

useMemo: Memoizing Values

useMemo is a React Hook that memoizes a computed value. Similar to useCallback, it prevents expensive calculations from being re-executed on every render if their dependencies haven't changed.

When to use it: Use useMemo when:

Example:

component.jsx
1import React, { useState, useMemo } from 'react';
2
3function ProductList({ products, filterTerm }) {
4  // Without useMemo, filteredProducts would be re-calculated on every render
5  // even if products and filterTerm haven't changed.
6  // const filteredProducts = products.filter(product =>
7  // product.name.includes(filterTerm)
8  // );
9
10  // With useMemo, filteredProducts is only re-calculated when products or filterTerm change
11  const filteredProducts = useMemo(() => {
12    console.log('Filtering products...');
13    return products.filter(product =>
14      product.name.includes(filterTerm)
15    );
16  }, [products, filterTerm]); // Dependencies
17
18  return (
19    <div>
20      {filteredProducts.map(product => ( 
21        <div key={product.id}>{product.name}</div> 
22      ))} 
23    </div>
24  );
25}
26
27function App() {
28  const [term, setTerm] = useState('');
29  const allProducts = useMemo(() => [ // Memoize the product data itself if it's static
30    { id: 1, name: 'Laptop' },
31    { id: 2, name: 'Keyboard' },
32    { id: 3, name: 'Mouse' },
33  ], []);
34
35  return (
36    <div> 
37      <input type="text" value={term} onChange={(e) => setTerm(e.target.value)} placeholder="Filter products..." /> 
38      <ProductList products={allProducts} filterTerm={term} />
39    </div>
40  );
41}
42
43export default App;

When Not to Memoize

While memoization is a powerful tool, it's not a silver bullet. Overuse can actually introduce its own overhead, as React needs to store and compare dependencies. Here's when you might want to skip memoization:

By understanding and strategically applying React.memo, useCallback, and useMemo, you can significantly improve the performance and responsiveness of your React applications. Remember, the goal is not to memoize everything, but to memoize intelligently where it yields the most benefit.

What are your go-to strategies for optimizing React performance? Share your tips in the comments!