0
0
ReactHow-ToBeginner · 4 min read

How to Use useCallback in React: Simple Guide with Examples

In React, useCallback is a hook that returns a memoized version of a callback function, which only changes if its dependencies change. Use it to prevent unnecessary re-creation of functions on every render, improving performance especially when passing callbacks to child components.
📐

Syntax

The useCallback hook takes two arguments: the function you want to memoize and an array of dependencies. It returns a memoized version of the function that only updates when one of the dependencies changes.

  • callback: The function you want to keep stable between renders.
  • dependencies: An array of values that, when changed, will update the memoized function.
javascript
const memoizedCallback = useCallback(() => {
  // Your function code here
}, [dependency1, dependency2]);
💻

Example

This example shows a parent component that uses useCallback to memoize a function passed to a child component. The child only re-renders when the memoized function changes, avoiding unnecessary renders.

javascript
import React, { useState, useCallback } from 'react';

const Child = React.memo(({ onClick }) => {
  console.log('Child rendered');
  return <button onClick={onClick}>Click me</button>;
});

export default function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    alert('Button clicked!');
  }, []); // No dependencies, function stays the same

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <Child onClick={handleClick} />
    </div>
  );
}
Output
When you click 'Increment', only the parent re-renders and 'Child rendered' does NOT log again because the memoized function did not change. Clicking 'Click me' shows an alert.
⚠️

Common Pitfalls

Common mistakes when using useCallback include:

  • Not listing all dependencies in the dependency array, causing stale closures.
  • Using useCallback unnecessarily for functions that don't cause re-renders or performance issues.
  • Expecting useCallback to fix all performance problems; it only helps with function identity.
javascript
import React, { useState, useCallback } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Wrong: missing 'count' in dependencies causes stale value
  const incrementWrong = useCallback(() => {
    setCount(count + 1); // 'count' is stale here
  }, []);

  // Right: include 'count' in dependencies
  const incrementRight = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <button onClick={incrementWrong}>Wrong Increment</button>
      <button onClick={incrementRight}>Right Increment</button>
      <p>Count: {count}</p>
    </div>
  );
}
Output
Clicking 'Wrong Increment' will not update count correctly because it uses a stale count value. 'Right Increment' updates count properly.
📊

Quick Reference

  • Purpose: Memoize functions to avoid re-creating them on every render.
  • Use when: Passing callbacks to optimized child components or expensive computations inside callbacks.
  • Dependencies: Always include all variables used inside the callback.
  • Don't use: For every function; only when it improves performance.

Key Takeaways

Use useCallback to memoize functions and prevent unnecessary re-renders.
Always include all dependencies in the dependency array to avoid stale data.
Avoid overusing useCallback; use it only when it improves performance.
Memoized functions keep the same identity unless dependencies change.
Combine useCallback with React.memo for best child component optimization.