useCallback Hook in React – Complete Guide with Examples

Introduction

React JS is widely used for building fast and interactive user interfaces. As applications grow in size and complexity, performance optimization becomes essential. React provides several hooks to help developers optimize performance, and one of the most important among them is the useCallback Hook.

In this article, we will understand what useCallback is, why it is used, how it works, and when to use it with real-world examples.

What is useCallback in React?

The useCallback Hook is used to memoize functions in React.

In simple words:

useCallback returns a cached version of a function that only changes when its dependencies change.

This helps prevent unnecessary re-creation of functions on every render.

Why do we need useCallback?

In React, every time a component re-renders:

  • All functions inside it are recreated again
  • Even if the logic is same, new function reference is created

This becomes a problem when:

  • You pass functions to child components
  • You use React.memo for optimization
  • You work with large applications

Problem Example:

Without useCallback, child components may re-render unnecessarily because function references keep changing.

Syntax of useCallback


const memoizedCallback = useCallback(() => {
 // function logic
}, [dependencies]);

Parameters:

  1. Function – The function you want to memoize
  2. Dependency array – Function is recreated only when dependencies change

Simple Example of useCallback


import React, { useCallback, useState } from "react";
function App() {
 const [count, setCount] = useState(0);
 const handleClick = useCallback(() => {
   console.log("Button clicked");
 }, []);
 return (
   <div>
     <h1>Count: {count}</h1>
     <button onClick={() => setCount(count + 1)}>
       Increase Count
     </button>
     <ChildButton onClick={handleClick} />
   </div>
 );
}
function ChildButton({ onClick }) {
 console.log("Child rendered");
 return <button onClick={onClick}>Click Me</button>;
}
export default App;

What is happening here?

  • handleClick is wrapped inside useCallback
  • It does NOT change on every render
  • So ChildButton does NOT re-render unnecessarily (if optimized with React.memo)

useCallback with React.memo

To fully benefit from useCallback, we often use it with React.memo.

Example:


import React, { useCallback, useState, memo } from "react";
const Child = memo(({ onClick }) => {
 console.log("Child rendered");
 return <button onClick={onClick}>Child Button</button>;
});
function App() {
 const [count, setCount] = useState(0);
 const handleClick = useCallback(() => {
   console.log("Clicked");
 }, []);
 return (
   <div>
     <h1>{count}</h1>
     <button onClick={() => setCount(count + 1)}>
       Increase
     </button>
     <Child onClick={handleClick} />
   </div>
 );
}
export default App;

Why this works better?

  • useCallback prevents function recreation
  • React.memo prevents child re-render
  • Together, they improve performance significantly

Difference Between useCallback and Normal Function

Feature Normal Function useCallback
Function Creation Every render Cached between renders
Reference Change Yes No (if dependencies unchanged)
Performance Lower in large apps Optimized
Use Case Simple apps Optimized React apps

When should you use useCallback?

You should use useCallback when:

1. Passing functions to child components

If child is optimized with React.memo.

2. Preventing unnecessary re-renders

When function reference changes cause re-rendering.

3. Handling large applications

Where performance matters.

Real-World Example: Input Handler Optimization


import React, { useCallback, useState, memo } from "react";
const Input = memo(({ onChange }) => {
 console.log("Input rendered");
 return <input onChange={onChange} placeholder="Type here..." />;
});
function App() {
 const [text, setText] = useState("");
 const handleChange = useCallback((e) => {
   setText(e.target.value);
 }, []);
 return (
   <div>
     <h2>Text: {text}</h2>
     <Input onChange={handleChange} />
   </div>
 );
}
export default App;

What happens here?

  • Input component will NOT re-render unnecessarily
  • Because function reference remains stable

useCallback vs useMemo

Many developers confuse these two hooks.
Hook Purpose
useCallback Memoizes functions
useMemo Memoizes values


Example difference:

const memoValue = useMemo(() => computeValue(a, b), [a, b]);


const memoFunction = useCallback(() => {
 console.log("Hello");
}, []);

Common Mistakes with useCallback

❌ 1. Using everywhere

Not all functions need memoization.

❌ 2. Wrong dependency array

Missing dependencies can cause stale function behavior.

❌ 3. Over-optimization

Sometimes it adds unnecessary complexity.

Advantages of useCallback

✔ Prevents unnecessary function creation
✔ Improves performance in large apps
✔ Works well with React.memo
✔ Reduces child component re-renders

Disadvantages of useCallback

❌ Slight memory overhead
❌ Can make code complex
❌ Not needed for small applications

Best Practices

✔ Use only when needed
✔ Combine with React.memo
✔ Keep dependency arrays accurate
✔ Avoid premature optimization

useCallback Hook – Interview Questions

Q 1: What is useCallback?
Ans: useCallback memoizes functions to prevent unnecessary re-creations.
Q 2: How is useCallback different from useMemo?
Ans: useCallback memoizes functions, while useMemo memoizes values.
Q 3: When should useCallback be used?
Ans: When passing functions as props to child components.
Q 4: Does useCallback improve performance?
Ans: Yes, especially when used with React.memo.
Q 5: What happens if dependencies change?
Ans: A new function is created.

useCallback Hook – Objective Questions (MCQs)

Q1. What is the main purpose of the useCallback hook in React?






Q2. Which syntax correctly uses useCallback?






Q3. Why is useCallback useful in React?






Q4. What happens if you do not provide a dependency array to useCallback?






Q5. Which of the following is TRUE about useCallback?






Conclusion

The useCallback Hook in React JS is a powerful performance optimization tool that helps prevent unnecessary function re-creation. It is especially useful when passing functions to child components and working with large-scale applications.

However, it should not be overused. React already optimizes most cases, so use useCallback only when you notice performance issues or unnecessary re-renders.

Continue Learning React