React useMemo Hook

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

  1. Setting Up a New React Project
  2. Syntax of useMemo
  3. Real-Time Project: Employee Management System with Filtered Employee List
    • Project Setup
    • Creating the Employee Component
    • Defining the Filtering Logic
    • Using useMemo to Optimize Filtering
  4. Conclusion

Setting Up a New React Project

First, let’s create a new React project using the create-react-app tool.

  1. Open your terminal and run the following command:

    npx create-react-app usememo-employee-app
    
  2. 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 useMemo hook is used to memoize the result of expensiveCalculation.
  • The expensive calculation is only recomputed when count changes, not when text changes.

Real-Time Project: Employee Management System with Filtered Employee List

Project Setup

  1. Open the project directory in your code editor.

  2. Remove the default content from src/App.js and src/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

  1. Create a new file named Employee.js in the src directory.

  2. Define the Employee component:

    // 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

  1. Memoize the Filtered Employees: The filteredEmployees array is memoized using useMemo and will only be recomputed when the employees or searchTerm dependencies 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

  1. Render the Search Input and Employee List: The search input and the list of employees are rendered based on the filteredEmployees array.

    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>
    );
    
  2. Create a CSS file named Employee.css to 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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top