DEV Community

Cover image for 💥 Turbocharging React with useMemo and useCallback: No More Slow Renders! 💨
Akash Kumawat
Akash Kumawat

Posted on

💥 Turbocharging React with useMemo and useCallback: No More Slow Renders! 💨

If you're anything like me, you love how smooth React can be... until it isn't! Yep, as your app grows and becomes more complex, you might start noticing some performance slowdowns. But fear not! React gives us a couple of awesome tools useMemo and useCallback to keep things running fast and smooth.

In this guide, we’ll break down these two hooks in a fun, friendly way, so you can optimize your app without breaking a sweat!

🧐 Wait, Why Bother? Isn’t React Fast Enough?

Great question! React is usually blazing fast. But sometimes, if you’re running expensive calculations or passing a lot of functions through your component tree, things can start to drag a bit. Every time your app re-renders (because props or state changed), React has to re-do a lot of stuff.

That’s where useMemo and useCallback come in. They basically let React “remember” stuff so it doesn’t have to re-do unnecessary work!


🧠 useMemo: Making React Remember the Hard Stuff!

Think of useMemo as a smart assistant. It keeps track of the result of a function and only recalculates it if something important changes. Why bother re-doing a calculation when the inputs haven’t even changed? Exactly.

The Basics:

const memoizedValue = useMemo(() => {
  return calculateSomethingExpensive(a, b);
}, [a, b]);
Enter fullscreen mode Exit fullscreen mode

In this example, calculateSomethingExpensive will only run if a or b change. Otherwise, React says, "No need to redo that work — I’ve got it saved right here!"

A Fun Example:

Let’s say we’re building a component that calculates the total value of a shopping cart. Every time the component re-renders, it recalculates that total. Now, if you’re shopping a lot (which we all do!), this calculation might slow down the app:

function ShoppingCart({ items }) {
  const totalValue = items.reduce((sum, item) => sum + item.price, 0);

  return <div>Total: {totalValue}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Even if the items haven’t changed, we’re still doing the math every time! With useMemo, we can tell React to only recalculate when the items array changes:

function ShoppingCart({ items }) {
  const totalValue = useMemo(() => {
    return items.reduce((sum, item) => sum + item.price, 0);
  }, [items]);

  return <div>Total: {totalValue}</div>;
}
Enter fullscreen mode Exit fullscreen mode

Boom! Now your app only recalculates when there’s actually something new in your cart. It’s like React saying, “I’ve got this covered.”


🔥 useCallback: No More New Functions Every Second!

Now let’s talk about useCallback. If useMemo is about remembering values, useCallback is about remembering functions. This is super useful when you’re passing a function as a prop to a child component.

Without useCallback, React recreates your function on every render — this can cause your child components to re-render unnecessarily. And we all know how annoying that can be!

The Basics:

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

This tells React to only recreate the doSomething function if a or b change. If not, React just reuses the previous function!

Let’s Break It Down:

Here’s a common scenario: You have a parent component passing down a handleClick function to a child component. But every time the parent re-renders, the function gets recreated, forcing the child to re-render too:

function ParentComponent() {
  const handleClick = () => {
    console.log('Button clicked!');
  };

  return <ChildComponent onClick={handleClick} />;
}
Enter fullscreen mode Exit fullscreen mode

Even if nothing has changed, the child component thinks it needs to re-render because the handleClick function is "new" every time.

Now, let’s be clever and use useCallback to avoid this:

function ParentComponent() {
  const handleClick = useCallback(() => {
    console.log('Button clicked!');
  }, []);

  return <ChildComponent onClick={handleClick} />;
}
Enter fullscreen mode Exit fullscreen mode

Tada! Now the handleClick function only changes if its dependencies change, and the child component doesn’t re-render unnecessarily.


🤔 useMemo vs. useCallback: What’s the Difference? (Spoiler: Both are Awesome!)

Okay, so now you’re probably thinking, “These two sound pretty similar—what’s the difference?”

  • useMemo: Caches the result of a function. It’s great when you have some expensive calculation that doesn’t need to be recalculated all the time.
  • useCallback: Caches the function itself. Perfect when you’re passing functions down as props and want to avoid unnecessary re-renders.

Quick Recap:

  • Use useMemo to avoid recalculating something unless it’s necessary.
  • Use useCallback to prevent creating new functions unless their dependencies have changed.

🚀 When Should You Actually Use These Hooks?

Here’s the golden rule: Don’t overuse useMemo and useCallback. Seriously! React is already fast enough for most apps, and using these hooks everywhere can add unnecessary complexity.

When to Use useMemo:

  • You’re doing something heavy, like filtering or sorting a large list, or performing complex math.

When to Use useCallback:

  • You’re passing functions down to child components, and you notice those components are re-rendering more than they need to (especially if they’re wrapped in React.memo).

Measure performance before and after using these hooks. If you notice a speed boost, great! If not, maybe it’s not worth the extra complexity.


😱 Pitfalls: Don’t Be That Person!

  • Overuse: Please, don’t slap useMemo or useCallback on every single function or calculation. It can actually hurt performance if used excessively. Only memoize when you need to.
  • Wrong Dependencies: If you forget to include the right dependencies in your dependency array, your memoized function might not update correctly. Always double-check what variables your function depends on.

🎉 Wrapping Up: Keep it Fun and Fast!

So there you have it! useMemo and useCallback are awesome tools to keep your React app snappy, but remember—React is already super fast. Use these hooks when you need to optimize performance, but don’t go overboard. Simplicity is key!

With that, go out there and make your app lightning-fast (and have fun while doing it)


Happy coding!

Top comments (3)

Collapse
 
dh336699 profile image
Scofield

But in actual development, if we find ourselves constantly worrying about function re-rendering, is there a better way to determine when to use useCallback?

Collapse
 
_akashkmt_ profile image
Akash Kumawat

Ah, I hear you! It can feel like a headache constantly worrying about function re-renders, right? 😅 Honestly, the best approach is to not sweat it too much unless you actually notice performance issues.

Instead of trying to pre-optimize everything with useCallback, I’d suggest just coding as usual. When (or if) you see re-renders slowing things down, that’s when you bring in the React Profiler or DevTools to check what's really causing the issue. It’s all about using useCallback where it counts, not everywhere.

So yeah, focus on writing clean code, and let React handle most of the heavy lifting until you see a problem! Hope that gives some peace of mind! 😄

Collapse
 
hanzla-mirza profile image
Mirza Hanzla

👍👍👍👍