DEV Community

Cover image for 🧠 Mastering useCallback in React: Prevent Unnecessary Re-Renders and Boost Performance
WebTechnology Tutorials
WebTechnology Tutorials

Posted on • Originally published at webcodingwithankur.blogspot.com

🧠 Mastering useCallback in React: Prevent Unnecessary Re-Renders and Boost Performance

Ever wondered why your child components keep re-rendering even when their props haven't changed? Or why performance drops in large React apps? The answer might lie in one powerful but underused hook β€” useCallback.

In this blog post, we’ll explore React’s useCallback hook in depth. You’ll learn how it works, when to use it, and how to pair it with tools like React.memo, useState, and useMemo for real-world performance optimization.


πŸ” What is useCallback in React?
useCallback is a React Hook that returns a memoized version of a callback function. It prevents the function from being re-created on every render β€” unless the dependencies change.

const memoizedFn = useCallback(() => { doSomething(a, b); }, [a, b]); 
Enter fullscreen mode Exit fullscreen mode

This becomes crucial when you're passing callbacks to memoized child components (React.memo), which rely on reference equality to avoid re-rendering.


🧠 Real-World Analogy
Think of your callback as a phone number. If it changes every time, the person you're calling (your child component) thinks it's someone new β€” and answers again. useCallback keeps the number the same unless there's a real reason to change.


βœ… Why Use useCallback?

  • Prevent unnecessary re-renders
  • Improve app performance
  • Stabilize function references passed as props
  • Avoid expensive recalculations

❌ Without useCallback

const Parent = () => { const [count, setCount] = useState(0); const handleClick = () => { console.log("Clicked"); }; return ( <> <button onClick={() => setCount(count + 1)}>Increment</button> <Child onClick={handleClick} /> </> ); }; const Child = React.memo(({ onClick }) => { console.log("Child re-rendered"); return <button onClick={onClick}>Click me</button>; }); 
Enter fullscreen mode Exit fullscreen mode

Here, Child re-renders even when it doesn’t need to β€” because handleClick is recreated on every render.


βœ… With useCallback

const handleClick = useCallback(() => { console.log("Clicked"); }, []); 
Enter fullscreen mode Exit fullscreen mode

Now the Child component won’t re-render unnecessarily, thanks to the stable function reference.


πŸ§ͺ useCallback vs useMemo

| Hook | Purpose | Returns | | ------------- | ----------------------- | ----------------------- | | `useCallback` | Memoizes a **function** | Same function reference | | `useMemo` | Memoizes a **value** | Result of computation | 
Enter fullscreen mode Exit fullscreen mode
const memoizedCallback = useCallback(() => compute(a, b), [a, b]); const memoizedValue = useMemo(() => compute(a, b), [a, b]); 
Enter fullscreen mode Exit fullscreen mode

πŸ” Debug With React DevTools
Use the Profiler in React DevTools to:

  • Inspect render frequency
  • Validate optimizations
  • Track function reference changes

βš™οΈ Best Practices

βœ… Use with React.memo for child components
βœ… Use when function dependencies change infrequently
βœ… Avoid overuse β€” it has memory overhead
βœ… Always pass accurate dependencies
βœ… Combine with useMemo when needed


πŸ’‘ Bonus: Working with useState

const [count, setCount] = useState(0); const increment = useCallback(() => { setCount(prev => prev + 1); }, []); 
Enter fullscreen mode Exit fullscreen mode

πŸ’¬ Let's Connect
Have questions or want to share how you use useCallback? Drop a comment below or explore more tips on my blog:
πŸ”— Mastering useCallback in React

Top comments (0)