Introduction
In this chapter, we will explore the useMemo hook in React. This hook allows you to memoize expensive calculations and return a memoized value, preventing unnecessary recalculations on every render. This can improve performance by optimizing how and when these calculations are performed. We will create a new React project from scratch, explain the syntax of useMemo, and walk through a real-time project step by step to demonstrate its usage.
Table of Contents
- Setting Up a New React Project
- Syntax of
useMemo - Real-Time Project: Employee Management System with Filtered Employee List
- Project Setup
- Creating the Employee Component
- Defining the Filtering Logic
- Using
useMemoto Optimize Filtering
- Conclusion
Setting Up a New React Project
First, let’s create a new React project using the create-react-app tool.
-
Open your terminal and run the following command:
npx create-react-app usememo-employee-app -
Navigate to the project directory:
cd usememo-employee-app
Syntax of useMemo
The useMemo hook returns a memoized value that is recomputed only when one of the dependencies changes. This is useful for optimizing expensive calculations.
Syntax
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
memoizedValue: The memoized value.computeExpensiveValue: The function to compute the value.[a, b]: An array of dependencies that, when changed, will cause the function to recompute the value.
Example
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const expensiveCalculation = (num) => {
console.log('Calculating...');
for (let i = 0; i < 1000000000; i++) {} // Simulate an expensive calculation
return num * 2;
};
const memoizedValue = useMemo(() => expensiveCalculation(count), [count]);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<p>Expensive Calculation Result: {memoizedValue}</p>
<input value={text} onChange={(e) => setText(e.target.value)} placeholder="Type something..." />
</div>
);
}
export default ExpensiveCalculation;
Explanation:
- The
useMemohook is used to memoize the result ofexpensiveCalculation. - The expensive calculation is only recomputed when
countchanges, not whentextchanges.
Real-Time Project: Employee Management System with Filtered Employee List
Project Setup
-
Open the project directory in your code editor.
-
Remove the default content from
src/App.jsandsrc/App.css:// src/App.js import React from 'react'; import './App.css'; import Employee from './Employee'; function App() { return ( <div className="App"> <h1>Employee Management System</h1> <Employee /> </div> ); } export default App;/* src/App.css */ .App { text-align: center; padding: 20px; } h1 { margin-bottom: 20px; }
Creating the Employee Component
-
Create a new file named
Employee.jsin thesrcdirectory. -
Define the
Employeecomponent:// src/Employee.js import React, { useState, useMemo } from 'react'; import './Employee.css'; const initialEmployees = [ { id: 1, firstName: 'John', lastName: 'Doe', email: 'john@example.com' }, { id: 2, firstName: 'Jane', lastName: 'Smith', email: 'jane@example.com' }, { id: 3, firstName: 'Sara', lastName: 'Williams', email: 'sara@example.com' }, ]; function Employee() { const [employees, setEmployees] = useState(initialEmployees); const [searchTerm, setSearchTerm] = useState(''); const handleSearch = (event) => { setSearchTerm(event.target.value); }; const filteredEmployees = useMemo(() => { console.log('Filtering employees'); return employees.filter((employee) => `${employee.firstName} ${employee.lastName} ${employee.email}` .toLowerCase() .includes(searchTerm.toLowerCase()) ); }, [employees, searchTerm]); return ( <div className="container mt-5"> <input type="text" className="form-control mb-3" placeholder="Search employees..." value={searchTerm} onChange={handleSearch} /> <ul className="list-group"> {filteredEmployees.map((employee) => ( <li key={employee.id} className="list-group-item"> {employee.id} - {employee.firstName} {employee.lastName} ({employee.email}) </li> ))} </ul> </div> ); } export default Employee;
Using useMemo to Optimize Filtering
-
Memoize the Filtered Employees: The
filteredEmployeesarray is memoized usinguseMemoand will only be recomputed when theemployeesorsearchTermdependencies change.const filteredEmployees = useMemo(() => { console.log('Filtering employees'); return employees.filter((employee) => `${employee.firstName} ${employee.lastName} ${employee.email}` .toLowerCase() .includes(searchTerm.toLowerCase()) ); }, [employees, searchTerm]);
Rendering the Component
-
Render the Search Input and Employee List: The search input and the list of employees are rendered based on the
filteredEmployeesarray.return ( <div className="container mt-5"> <input type="text" className="form-control mb-3" placeholder="Search employees..." value={searchTerm} onChange={handleSearch} /> <ul className="list-group"> {filteredEmployees.map((employee) => ( <li key={employee.id} className="list-group-item"> {employee.id} - {employee.firstName} {employee.lastName} ({employee.email}) </li> ))} </ul> </div> ); -
Create a CSS file named
Employee.cssto style the Employee component:/* src/Employee.css */ .container { max-width: 600px; margin: 0 auto; text-align: left; } .form-control { width: 100%; padding: 10px; margin: 5px 0; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; } .list-group-item { display: flex; justify-content: space-between; align-items: center; padding: 10px; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 10px; }
Conclusion
In this chapter, we created a new React project and explored the useMemo hook. We learned the syntax of useMemo and walked through a real-time project step by step to create an Employee Management System application with optimized filtering functionality. By understanding and using the useMemo hook, you can memoize expensive calculations and prevent unnecessary recalculations, making your React applications more performant and efficient.