React Course
React
/
Advanced

useCallback

Definition

`useCallback` is a React Hook that lets you cache a function definition between re-renders. It is primarily used to prevent unnecessary re-renders of child components that rely on reference equality to avoid updating.

Explain Like I'm New

Imagine you have a 'recipe' (a function) for baking cookies. Every time you clean your kitchen (re-render), you throw away the old recipe and write a brand new identical recipe. If you hand that recipe to your friend (a child component), they think it's a completely new recipe and they start baking again! `useCallback` is like laminating the recipe. You keep the exact same physical copy, so your friend knows nothing has changed.

Real World Example

You have a massive `<HeavyChart />` component wrapped in `React.memo()`. You pass it an `onClick={handlePointClick}` function. If you don't wrap `handlePointClick` in `useCallback`, a brand new function is created in memory on every render. The Chart sees a 'new' function prop, and re-renders entirely, completely defeating `React.memo`.

Common Use Cases

  • Passing stable callback functions to heavily optimized child components (like those using `React.memo`)
  • Preventing infinite loops when a function is used as a dependency in a `useEffect` array

React Performance Hooks Comparison

HookWhat it cachesPrimary Use Case
`useCallback`A Function DefinitionPreventing a child component from unnecessarily re-rendering when you pass it a callback function as a prop.
`useMemo`A Computed ValuePreventing an expensive math calculation or data filtering operation from running on every single render.
`useEffect`Nothing (Runs side-effects)Fetching data, setting up subscriptions, or manually changing the DOM.

Interactive Example

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

// A child component heavily optimized with React.memo
// It will ONLY re-render if 'title' or 'onAction' changes in memory.
const HeavyChild = React.memo(({ title, onAction }) => {
  console.log("HeavyChild rendered!");
  return <button onClick={onAction}>{title}</button>;
});

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

  // BAD: This creates a brand new function in memory every time Parent renders.
  // If we passed this, HeavyChild would re-render every time 'count' changes.
  // const handleAction = () => console.log("Action!");

  // GOOD: useCallback caches the function in memory.
  // It will always be the exact same function reference.
  const handleAction = useCallback(() => {
    console.log("Action clicked!");
  }, []); // Empty array means it never needs to be recreated

  return (
    <div>
      <h2>Parent Count: {count}</h2>
      <button onClick={() => setCount(c => c + 1)}>Increment Parent</button>
      
      <hr />
      {/* Passing the cached function to the optimized child */}
      <HeavyChild title="Click Me" onAction={handleAction} />
    </div>
  );
}

Interview Questions

basic

  • What is the main purpose of `useCallback`?
  • How is `useCallback` different from `useMemo`?

intermediate

  • If you wrap a function in `useCallback`, but you don't pass it to a child component, is it helping performance?
  • What causes a `useCallback` function to be recreated?

advanced

  • Why is inline function creation (e.g., `onClick={() => doSomething()}`) usually perfectly fine for standard DOM elements like `<button>`?
  • How does JavaScript's concept of 'Reference Equality' apply to `useCallback`?

trick

  • Does `useCallback` make your component render faster?

Flash Cards

Question

How is useCallback different from useMemo?

Click to reveal answer
Answer

`useMemo` calls your function during render and caches the RESULT. `useCallback` does NOT call your function; it simply caches the FUNCTION ITSELF so it maintains the exact same memory address across renders.

Question

Is inline function creation fine for standard DOM elements like <button>?

Click to reveal answer
Answer

Yes! Standard HTML elements (like `div` or `button`) are not wrapped in `React.memo`. They are blazing fast to evaluate. Wrapping an `onClick` for a regular `<button>` in `useCallback` is actually worse for performance, because you add the overhead of the hook for zero benefit.

Question

Does useCallback make your component render faster?

Click to reveal answer
Answer

No, it actually makes the component it is defined inside slightly SLOWER because of the hook overhead. Its only purpose is to make CHILD components render faster by skipping renders via `React.memo`.