useMemo in React

Sandeep Kumar Dev
3 min readMay 15, 2021

React’s useMemo Hook can be used to optimize the computation costs of your React function components. We will go through an example component to illustrate the problem first, and then solve it with React’s useMemo Hook.

Keep in mind that most of the performance optimizations in React are premature. React is fast by default, so every performance optimization is opt-in in case something starts to feel slow.

Note: Don’t mistake React’s useMemo Hook with React’s memo API. While useMemo is used to memoize values, React memo is used to wrap React components to prevent re-renderings.

Note: Don’t mistake React’s useMemo Hook with React’s useCallback Hook. While useMemo is used to memoize values, useCallback is used to memoize functions.

Let’s take the following example of a React application which renders a list of users and allows us to filter the users by their name. The catch: The filter happens only when a user explicitly clicks a button; not already when the user types into the input field:

import React from "react";

const users = [
{ id: 1, name: "Noble" },
{ id: 2, name: "Nichole" },
{ id: 3, name: "Colleen" },
{ id: 4, name: "Linnie" },
{ id: 5, name: "Kristy" },
{ id: 6, name: "Stacy" },
{ id: 7, name: "Maryjane" },
{ id: 8, name: "Kaylin" },
];

const App = () => {
const [input, setText] = React.useState("");
const [searchText, setSearchText] = React.useState("");

const handleText = (event) => {
setText(event.target.value);
};

const handleSearch = (e) => {
e.preventDefault();
setSearchText(input);
};

const filteredUsers = users.filter((user) => {
console.log("Filter function is running...");
return user.name.toLowerCase().includes(searchText.toLowerCase());
});

return (
<form onSubmit={handleSearch}>
<input type="text" value={input} onChange={handleText} />
<List list={filteredUsers} />
</form>
);
};

const List = ({ list }) => {
return (
<ul>
{list.map((item) => (
<ListItem key={item.id} item={item} />
))}
</ul>
);
};

const ListItem = ({ item }) => {
return <li>{item.name}</li>;
};

export default App;

Even though the filteredUsers don't change when someone types into the input field, because they change only when clicking the button via the search state, the filter's callback function runs again and again for every keystroke in the input field:

const filteredUsers = users.filter((user) => {
console.log("Filter function is running...");
return user.name.toLowerCase().includes(searchText.toLowerCase());
});

This doesn’t slow down this small React application. However, if we would deal with a large data set in this array and run the filter’s callback function for every keystroke, we would maybe slow down the application. Therefore, you can use React’s useMemo Hook to memoize a function return value(s) and to run a function only if its dependencies (here search) have changed:

const filteredUsers = React.useMemo(
() =>
users.filter((user) => {
console.log("Filter function is running...");
return user.name.toLowerCase().includes(searchText.toLowerCase());
}),
[searchText]
);

Now, this function is only executed once the search state changes. It doesn't run if the text state changes, because that's not a dependency for this filter function and thus not a dependency in the dependency array for the useMemo hook.

Thank You for reading. Happy Coding🧑‍💻

--

--