#React.js: 🚀 Understanding useCallback and useMemo: A Practical Guide
When and why you should (or shouldn’t) use them? | ♻️ Knowledge seeks community #5
Hey, hey! 👋
Welcome back to Stef’s Dev Notes! 🚀
Hope you've been enjoying the latest articles. If you have any feedback, feel free to reply to this email or DM me on Substack—I’d love to hear your thoughts!
This week, we’re diving into performance optimization in React.js with two underrated but powerful hooks: useCallback
and useMemo
. Let’s explore when and why you should (or shouldn’t) use them!
🌟 Introduction
Performance optimization is an essential part of building efficient React applications. While React's reconciliation process is designed to be fast, unnecessary re-renders and computations can still have a negative impact on performance.
Two powerful hooks, useCallback
and useMemo
, help mitigate these issues by memoizing functions and computed values, respectively. While they’re often mentioned together, they serve different purposes and are designed to solve different performance issues.
But when should you use them, and when are they overkill? Let's dive in.
🚀 Understanding useCallback()
What is useCallback()
?
useCallback()
is a React hook that memoizes a function reference so that it remains the same across renders unless its dependencies change. In simpler terms, it helps prevent unnecessary re-renders by returning a cached version of a function. This is particularly useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.
When to use useCallback
?
When passing functions as props to
React.memo
components to avoid unnecessary re-renders.When adding event listeners inside
useEffect
to prevent multiple re-registrations.When memoizing handlers to avoid frequent re-creation of functions.
Example: Using useCallback
when Passing Functions to Optimized Child Components
The most common use case is when you're passing callbacks to components that are wrapped in
React.memo()
.
Without
useCallback
:Here,
handleSelect
fromList
component is re-created on every render causing allListItem
components to re-render.
With
useCallback
,handleSelect
maintains the same reference between renders andReact.memo
used inListItem
prevents unnecessary re-renders.
When NOT to use useCallback
?
If a function isn't passed as a prop,
useCallback
doesn’t provide any benefit.If the function is lightweight, the performance gain is negligible.
🚀 Understanding useMemo()
What is useMemo
?
useMemo
is somehow similar to useCallback
, but instead of memoizing a function, it memoizes the result of a function call. Its purpose is to help with expensive calculations that should not be re-computed on every re-render.
When to use useMemo()
?
For expensive calculations, such as filtering large lists.
For memoizing derived state, preventing re-computation when dependencies haven't changed.
For optimizing dependencies inside
useEffect
.
Example: Using useMemo
for an Expensive Computation - list filtering.
Imagine having a large list of programming languages, and the user can filter them by name.
Without
useMemo
, the filtering logic runs on every render, even when unnecessary.With
useMemo
, the filtering only runs when necessary (when search updates), reducing unnecessary calculations and improving performance - especially for large datasets.
When NOT to use useMemo
?
If the computation is fast,
useMemo
adds unnecessary complexity.If dependencies change frequently, memoization won’t help much.
🔍 How to Measure Performance Before Optimizing
Before using useCallback
or useMemo
, it's a good practice to profile your app and check if unnecessary re-renders are happening. React provides tools to help with this.
1. Use React DevTools Profiler
React DevTools includes a Profiler that shows how often components re-render. Here’s how you can use it:
Open your app in Chrome or Firefox.
Install React Developer Tools.
Go to the Profiler tab and start recording.
Interact with your UI (e.g., filter the list or select an item).
Stop recording and check which components re-rendered unnecessarily.
2. Add Console Logging to Spot Re-Renders
A simple trick is to log when a component re-renders.
If you see every item re-rendering unnecessarily, it’s a sign you might need
useCallback
.
3. Compare Performance With and Without Optimization
Use React Profiler to compare before and after adding useMemo
or useCallback
.
If you see fewer renders, your optimization helped.
If there’s no improvement or more complexity, you might not need these hooks.
🌟 Conclusion
Both useCallback
and useMemo
are powerful tools for optimizing React applications, but they should be used only when necessary. A good rule of thumb is to start without these optimizations and add them only when you identify performance issues through profiling.
Remember:
Use
useCallback
for memoizing functions, especially when passing to optimized child componentsUse
useMemo
for expensive calculations or to prevent object recreationMeasure performance impact before and after applying optimizations
When used correctly, these hooks can significantly improve your application's performance, especially in complex or data-heavy interfaces.
Until next time 👋,
Stefania
P.S. Don’t forget to like, comment, and share with others if you found this helpful!
🎲 Try it yourself!
Here’s a CodeSandbox interactive demo where you can experiment with both useMemo
and useCallback
.
I recommend removing the hooks and watching the developer console to see how often the components re-render. Then, reintroduce them to observe the performance improvements in action! 🚀
Play with useCallback and useMemo
Other articles from the ♻️ Knowledge seeks community 🫶 collection: https://stefsdevnotes.substack.com/t/knowledgeseekscommunity
👋 Get in touch
Feel free to reach out to me here on Substack or on LinkedIn.
This was a very insightful article on useMemo and useCallback in React.js. Honestly, I always wondered why useCallback was needed. Now I understand. 😊
I used React.js before, and my past self said thank you!