`useCallback` vs `useMemo` Hooks

Sivasubramaniyam - Sep 19 - - Dev Community

React Learning Guide

Boosting React Performance: useCallback vs. useMemo Hooks

React's useCallback and useMemo hooks are crucial for optimizing performance in your applications. Understanding when and how to use them can save you from unnecessary re-renders and ensure your app runs smoothly. In this article, we'll dive into real-world examples of using useCallback and useMemo effectively.

When to Use useCallback

The useCallback hook returns a memoized version of the callback function, which means it only recreates the function if one of its dependencies changes. This is particularly useful when passing functions as props to child components to prevent them from re-rendering unnecessarily.

Real-time Example: Preventing Unnecessary Re-renders

Suppose you have a parent component that passes a function to a child component. Without useCallback, the child component would re-render every time the parent component renders, even if the function logic hasn't changed.

import React, { useState, useCallback } from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  const [count, setCount] = useState(0);

  // Using useCallback to memoize the function
  const handleIncrement = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <h1>Count: {count}</h1>
      <ChildComponent onIncrement={handleIncrement} />
    </div>
  );
};

export default ParentComponent;
Enter fullscreen mode Exit fullscreen mode

In the example above, handleIncrement is memoized with useCallback. The ChildComponent will only re-render when count changes, preventing unnecessary re-renders and improving performance.

When to Use useMemo

The useMemo hook is used to memoize the result of a function, recomputing the cached result only when one of its dependencies changes. It's useful for optimizing performance in situations where a function performs an expensive calculation.

Real-time Example: Optimizing Expensive Computations

Let's say you have a component that performs a computationally expensive operation, like filtering a large list.

import React, { useState, useMemo } from 'react';

const ExpensiveComponent = ({ items }) => {
  const [filter, setFilter] = useState('');

  // Using useMemo to optimize expensive filtering
  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter(item => item.includes(filter));
  }, [items, filter]);

  return (
    <div>
      <input
        type="text"
        value={filter}
        onChange={(e) => setFilter(e.target.value)}
        placeholder="Filter items"
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default ExpensiveComponent;
Enter fullscreen mode Exit fullscreen mode

In this example, useMemo is used to cache the result of filtering the items array. This way, the expensive filtering operation is only recalculated when items or filter changes, avoiding unnecessary computations.

Guidelines for Using useCallback and useMemo

  • Use useCallback when passing functions to child components to avoid unnecessary re-renders.
  • Use useMemo for expensive computations that don't need to be recalculated on every render.
  • Avoid overusing them. Memoization adds complexity and can sometimes make code harder to read. Only use them when you identify a performance issue.
  • Remember the dependencies array. Always specify dependencies accurately; otherwise, you might run into bugs or unexpected behavior.

Conclusion

React's useCallback and useMemo hooks are powerful tools for optimizing component performance by avoiding unnecessary re-renders and expensive calculations. By carefully applying these hooks, you can ensure your React application runs efficiently.

. . . . . . . . . . . .
Terabox Video Player