Optimize Your React App’s Performance with useMemo and useCallback
As HTML pages grow in size and complexity, creating efficient React code becomes crucial. Re-rendering large components can be costly, increasing processing time and potentially driving away users. Fortunately, React offers built-in API features to improve app performance by avoiding unnecessary re-renders, caching repetitive costly operations, and lazy-loading components.
React Performance Optimizations for Functions
React already provides React.memo()
to avoid recreating DOM elements when props are not changed. However, this method doesn’t memoize typical JavaScript functions. Therefore, despite being a first-class citizen in JavaScript, functions may potentially be recreated with every use. The useMemo
and useCallback
methods help avoid recreating or rerunning functions in certain situations.
What is useCallback?
When React re-renders a component, function references inside the component get re-created. If you pass a callback function to a memoized (with React.memo
) child component via props, it may get re-rendered even if the parent component doesn’t apparently change the child component’s props. Each parent component re-rendering phase creates new function references for callbacks, so inequal callback props can trigger an unwanted child component re-render silently even visible props don’t get changed.
A Practical Callback Example for useCallback
Let’s create a React project with Create React App and examine an example source code that passes a callback function to a memoized child component. We’ll see how useCallback
helps eliminate unwanted re-renders by providing a cached function reference.
Pros and Cons of Using useCallback
Here’s a table to understand the pros and cons of using useCallback
as a performance enhancement in your React apps:
| Pros | Cons |
| — | — |
| Avoids unnecessary re-renders | Overusing useCallback
can worsen performance issues |
| Provides a cached function reference | Adds overhead associated with wrapping functions |
What is useMemo?
In some scenarios, we have to include complex calculations in our React components. These complex calculations are inevitable and may slow down the rendering flow. If you had to re-render a component that handles a costly calculation to update another view result (not the result of the costly calculation), the costly calculation may get triggered again, ultimately causing performance issues.
A Practical Example for useMemo
Let’s look at an example source code that does a costly calculation with one state field. We’ll see how useMemo
helps avoid repeatedly performing potentially costly operations until necessary.
Pros and Cons of Using useMemo
Here’s a table to understand the pros and cons of using useMemo
as a performance enhancement in your React apps:
| Pros | Cons |
| — | — |
| Caches complex calculation results | Overusing useMemo
can worsen performance issues |
| Avoids repeatedly performing costly operations | Adds overhead associated with caching values |
Referential Equality in useMemo and useCallback
React uses JavaScript’s referential equality concept for comparing two identifiers. This means that React checks if the references are equal, not the actual values. This approach helps improve performance but requires careful consideration when using useMemo
and useCallback
.
Working with useCallback vs. useMemo in React
While both Hooks appear similar, there are specific use cases for each. Wrap functions with useCallback
when passing a callback function as a prop to a memoized component or as a dependency to other Hooks. Use useMemo
when caching expensive calculations or memoizing a dependency of another Hook.
How to Improve Your React Performance with useMemo and useCallback
To optimize your React app’s performance, follow these steps:
- Identify performance issues through code review or profiling tools.
- Measure actual rendering performance and code execution time using Chrome DevTools, console.time(), or React Profiler.
- Decide and use
useMemo
oruseCallback
accordingly. - Measure performance again to ensure improvements.
useCallback and useMemo Anti-Patterns
Overusing useCallback
and useMemo
can worsen existing performance issues. Be cautious when wrapping functions or caching values, as it adds overhead associated with wrapping functions or caching values.
By understanding how and when to use useCallback
and useMemo
, you can fine-tune your React app’s performance and provide a better user experience.