Learn

When React loads a component, it not only renders the JSX code but also evaluates all of the code and functions inside the component. Some components require functions that take a long time to execute, including API calls on a slow network or large database queries. If this occurs every time the component is rendered, and if the component re-renders frequently, the overall performance of the application will be compromised.

Often, the data returned by calls to APIs don’t change between component re-renders. It would be nice if we could instruct React to only call these expensive functions when new data is needed, and have it return a cached result when the data is the same. Luckily, React provides a hook that can help us optimize expensive function calls, named useMemo().

useMemo() utilizes an optimization technique called memoization. This technique caches the result of a function call and only calls the function again when its dependencies change.

React’s useMemo() hook takes two arguments. The first argument is a function and the second is an array of dependencies. If any of the dependencies change, React will recompute the result of the function. Its syntax looks like this:

import { useMemo } from 'react'; function DatabaseQuerier({ query }) { const queryResult = useMemo(() => { return expensiveDatabaseQuery(query) }, [query]); // ... }

In this example, the DatabaseQuerier component uses the time consuming expensiveDatabaseQuery() function. However, thanks to useMemo(), the queryResult returned will only be recomputed if the query dependency changes.

There are some notable behaviors of useMemo(): The function passed to useMemo() will be called when the component mounts, so it will always be called at least once. The dependency list works just like useEffect()‘s dependency list: If the list is empty, then it will only run on the first rendering of the component. We often want to pass in a dependency list that matches the arguments of the expensive function executed within the useMemo() callback. This ensures that any changes to the input of the function will give us an updated output. The dependency list is not passed as arguments to the function, but in most cases, the dependency list should be the same as the arguments passed to the function.

Note: The coding exercises in this lesson will be completed off-platform. If you have not done so yet, check out our article on Setting up Visual Studio Code before getting started.

Instructions

Task 1

Download the React Optimization Lesson Application

Download the application starting code by clicking on the link above and save it somewhere you can easily access it. Then, open it using your favorite code editor (we recommend VS Code).


Task 2

In the root folder of the project, install dependencies by running the terminal command npm install. This will install the dependencies of create-react-app, along with react-router-dom.


Task 3

Run the project with the terminal command npm start, then navigate to http://localhost:3000 in a browser.


Task 4

Click on the link “Exercise 2: Memoizing Values”. Click the “Show Explainers” button and see that the application does not respond immediately. The delay is subtle, but it’s there.


Task 5

Open the React profiler developer tool and record a session to see how slow the interaction is and which component is causing the performance bottleneck.

Hint

When recording the session, click the “Show Explainers” button a few times. Once we stop the recording, look in the flame graph for yellow bars. Pay close attention to the IsPrime bar. Look at how long it takes to render compared to the Exercise2 bar.


Task 6

Ideally, this interaction would take fractions of a millisecond instead of hundreds or thousands of milliseconds. Open /src/pages/Exercise2/IsPrime.js in a code editor. Inside this component, there is an expensive function named checkIfPrime(). Add memoization to this function with the useMemo() hook.

Hint

We can add the useMemo() hook by importing useMemo from 'react'. Then, we can make the checkIfPrime() function the first argument to useMemo(), and number the only variable in useMemo()‘s list of dependencies, like this:

import { useMemo } from 'react'; const isPrime = useMemo(() => checkIfPrime(number), [number]);

If you’re stuck, you can find the solution code in ./src/pages/Exercise2/solution/IsPrime.js.


Task 7

Reload the page, then open the React profiler again and record another session while you click the “Show Explainers” button on and off. In the resulting flame graph, notice how much faster IsPrime renders now compared to before you implemented useMemo().

Sign up to start coding

Mini Info Outline Icon
By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.

Or sign up using:

Already have an account?