ReactJS-The Beginner Master Class
  • React In the Beginning
    • Lesson 1 - Demo: Build a Simple React App - Fast
    • Lesson 2 - HTML Review
    • Lesson 3 - CSS Review
    • Lesson 4 - Modern JavaScript (JSX) Patterns
    • Lesson 5 - Set up Dev Environment
    • Hands-on Practice
  • React Fundamentals
    • Lesson 1 - Understanding Old vs New Way of Building Web Apps - SPAs
    • Lesson 2 - Motivation for Using React as the Solution to Vanilla JS
    • Lesson 3 - What is ReactJS - How it Works
    • React Code Along from Scratch
    • Lesson 4 - Create and Run a React Project with Vite - Full Overview
    • Lesson 5 - Create Hook by State Management in React
    • Lesson 6 - React Project File and Folder Walkthrough
    • Lesson 7 - JSX and How React Treats the DOM & JSX Compilation(by Babeljs) - Overview
    • Lesson 8 - Understanding the Main Files - App.jsx and main.jsx
    • Lesson 9 - Props and One-Way Data Flow - Overview
    • Lesson 10 - Google Bookshelf App - Ver 1.0
    • Hands-on Practice I
    • Hands-on Practice II
  • React State and Styling
    • Lesson 1 - Pulling Book Data from a Different Data File
    • Lesson 2 - Overview of How State Works in React
    • Lesson 3 - RandomQuote App
    • Lesson 4 - Lifting State Up - React Pattern Overview
    • Hands-On - Simple Counter
  • Forms and Interactivity - Grocery List App
    • Lesson 1 - Setup a Simple Form and Input
    • Lesson 2 - Build Form Profile App Using Multi-input Form Data
    • Hands-on : Build a Grocery List App
  • Connecting to the Backend - Consuming APIs - UseEffect Hook
    • Lesson 1 - Connecting to the Back End - Understanding Side Effects, Hooks and useEffect - Overview
    • Lesson 2 - Fetching Data from the Backend the Right Way with useEffect Hook
    • Lesson 3 - Setting Up Loading State
    • Hands-on :Use Dependency Array and Adding Values that Control Side Effects
  • Solo Project 1
  • RESTful APIs :Build a BookSearch App -Ver 2.0
    • Lesson 1: Build and test RESTful APIs with Postman
    • Lesson 2 - BookShelf App Structure
    • Lesson 3 - Create NavBar.jsx Component
    • Lesson 4 - Create Footer Component
    • Lesson 5 - Create BookList.jsx Component
    • Lesson 6 - Create BookCard.jsx Component
    • Lesson 7 - Creating Custom Hooks - useBooks and api-client
    • Lesson 8 - Controlling Network Activities in React with AbortController
    • Lesson 9 - Show Book Details in a Modal - Working
    • Lesson 10 - Bookshelf App Summary
  • Multi-Page Applications (MPAs)
    • Build a Multi-Page React Application
    • Multi-Page React Application
    • Hands-on Practice
  • Backend Frameworks-NEXT.JS
    • Migrating from React to Next.js
    • Lesson 1: Key Concepts of NodeJS and Express for Backend Web Development
    • Lesson 2: How to set up a new Next.js project
    • Lesson 3: How to create Layouts and Pages
    • Hands-on Practice 1
    • Hands on Practice 2
      • New Project & Folder Structure
      • File-Based Routing
      • Server vs Client Components & Router Hooks
      • Start On The Navbar
      • Navbar Links, Dropdowns & React Icons
      • Active Links & Conditional Rendering
      • Homepage Components
      • Properties Page
      • Property Card Dynamic Data
      • Home Property Listings
      • Custom Not Found & Loading Pages
  • Git and GitHubs
    • Git Installation
    • Git Commands
    • GitHub Repository
    • Hands-on Practice
  • Database in Application
    • React Supabase CRUD
    • Hands-on: Note Taking App
  • NoSQL Database
    • Installing MongoDB Community Edition
    • System Env Path Setting
    • How to use MongoDB Shell
    • How to Connect and Use Mongosh in VS Code via MongoDB Extension
    • MongoDB Guide
  • Solo Project 2
  • Deployment and Web Hosting
    • Lesson 1. React+Vite+TS+Shadcn Project
    • Lesson 2. Deploying a React Vite App to Vercel from Vercel CLI
    • Lesson 3 Connecting to GitHub Repo and Automate Deployment
  • Solo Project 3
  • Final Term Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 2 Team Project
    • Level 2 Team Project
    • Level 3 Team Project
    • Level 3 Team Project
Powered by GitBook
On this page
  • 1. Controlling Network Activities in React
  • What is AbortController?
  • Use Cases in React
  • How to Implement AbortController in React
  • Example Custom Hook (useBook)
  • Key improvements in this example:
  • 2. Step-by-Step Explanation of Implementing AbortController in React
  • Google BookShelf React App v2 : Result with AbortController
  1. RESTful APIs :Build a BookSearch App -Ver 2.0

Lesson 8 - Controlling Network Activities in React with AbortController

1. Controlling Network Activities in React

This section describes how to implement an abort controller in a React application using a custom hook. The goal is to prevent memory leaks and unnecessary network activity by managing HTTP requests. A custom hook, useBook, incorporates the AbortController to cleanly stop fetching data when a component unmounts. This is achieved by passing a signal to the fetch method and using the useEffect hook's cleanup function to call controller.abort(). This ensures that requests are aborted when the component is no longer needed, improving application performance and resource management. The explanation uses the example of fetching book data.

Controlling network activities in React with AbortController is crucial for preventing memory leaks and optimizing performance. Here's an explanation of how it works, its use cases, and implementation:

What is AbortController?

AbortController is a built-in browser API that allows you to abort one or more web requests. It's particularly useful in React applications for managing asynchronous operations like fetching data. Without proper control, if a component unmounts while a fetch request is still in progress, it can lead to:

  • Memory leaks: The component is gone, but the request might still resolve, attempting to update state on an unmounted component, causing errors.

  • Wasted resources: The browser continues to process the request even though the result is no longer needed.

Use Cases in React

  1. Preventing state updates on unmounted components: This is the primary use case. If a component initiates a fetch request and unmounts before the response arrives, attempting to setState will result in a warning or error. AbortController prevents this.

  2. Cancelling ongoing requests when user navigates or performs other actions: For example, if a user starts typing in a search bar that triggers API calls, you might want to abort previous requests when the user types a new character to avoid unnecessary network traffic.

  3. Implementing timeouts: Although AbortController doesn't directly implement timeouts, it can be combined with setTimeout to achieve similar behavior.

How to Implement AbortController in React

The most common and recommended approach is using a custom hook. Here's a breakdown:

  1. Create an AbortController instance: Inside your custom hook (or component), create a new instance of AbortController:

    JavaScript(jsx)

    const controller = new AbortController();
    const signal = controller.signal;
  2. Pass the signal to the fetch request: The signal property of the AbortController is passed as an option to the fetch function:

    JavaScript(isx)

    fetch('/api/books', { signal })
      .then(response => response.json())
      // ... handle the response
      .catch(error => {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted'); // Handle abort specifically
        } else {
          // Handle other errors
        }
      });
  3. Abort the request in the useEffect cleanup function: The crucial step. Use the useEffect hook with a cleanup function to abort the request when the component unmounts or when the dependencies of the useEffect change:

    JavaScript(jsx)

    useEffect(() => {
        // ... (fetch logic from step 2)
    
        return () => {
            controller.abort(); // Abort the fetch
        };
    }, [/* dependencies */]); // Add dependencies if needed

Example Custom Hook (useBook)

JavaScript(jsx)

import { useState, useEffect } from 'react';

function useBook(bookId) {
  const [book, setBook] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    const fetchBook = async () => {
      try {
        const response = await fetch(`/api/books/${bookId}`, { signal });
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        setBook(data);
      } catch (error) {
        if (error.name === 'AbortError') {
          console.log('Fetch aborted');
        } else {
          setError(error);
        }
      } finally {
        setLoading(false);
      }
    };

    fetchBook();

    return () => controller.abort();
  }, [bookId]);

  return { book, loading, error };
}

export default useBook;

Key improvements in this example:

  • Error handling: Includes more robust error handling, including checking for non-OK HTTP responses.

  • finally block: Ensures setLoading(false) is always called, even if there's an error or the request is aborted.

  • Async/await: Uses async/await for cleaner asynchronous code.

By using AbortController in this way, you can effectively manage network requests in your React applications, preventing memory leaks and improving performance.

2. Step-by-Step Explanation of Implementing AbortController in React

Objective

To efficiently manage HTTP requests and prevent memory leaks by using AbortController within a custom hook (useBooks) in a React application.


Step 1. Concept of AbortController

  • What it Does:

    • Allows you to cancel ongoing network requests when they are no longer needed (e.g., component unmounts or requests overlap).

  • How it Works:

    • Create an instance of AbortController.

    • Pass its signal property to the fetch API.

    • Use the abort() method to cancel the request.


Step 2. Updating useBooks Custom Hook

The hook now incorporates AbortController to manage fetch requests.

Code Highlights - useBooks.js

// useBooks.js - before using AbortController

import { useState, useEffect } from 'react'
import { fetchBooks } from './api-client.js'

const useBooks = (query) => {
  const [books, setBooks] = useState([])
  const [error, setError] = useState(null)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    
    const fetchBookData = async () => {
      setLoading(true)
      setError(null)
      try {
        const bookData = await fetchBooks(query)
        setBooks(bookData)
      } catch (err) {
        //setError(err.message)
        if (err.name !== 'AbortError') {
          setError(err.message)
        }
      } finally {
        setLoading(false)
      }
    }

    if (query) {
      fetchBookData()
    }

  }, [query])

  return { books, error, loading }
}

export default useBooks
// useBooks.js (updated with AbortController)
import { useState, useEffect } from 'react'
//import { fetchBooks } from './api-client.js'
import { fetchBooks } from './api-client-signal.js'

const useBooks = (query) => {
  const [books, setBooks] = useState([])
  const [error, setError] = useState(null)
  const [loading, setLoading] = useState(false)

  useEffect(() => {
    // Create an Abort Controller
    const controller = new AbortController() // Create an AbortController instance

    const fetchBookData = async () => {
      setLoading(true)
      setError(null)
      try {
        // const bookData = await fetchBooks(query)
        // pass AbortController signal to fetchBooks
        const bookData = await fetchBooks(query, controller.signal) // Pass signal to fetchBooks
        setBooks(bookData)
      } catch (err) {
        //setError(err.message)
        if (err.name !== 'AbortError') {
          setError(err.message)
        }
      } finally {
        setLoading(false)
      }
    }

    if (query) {
      fetchBookData()
    }

// if you refresh the browser, the code below will kick in and abort the requests!
  // return () => {
  //   controller.abort();
  // };

  }, [query])

  return { books, error, loading }
}

export default useBooks

Behavior

  • The AbortController cancels any active requests when:

    • The component unmounts.

    • The query changes.


Step 3. Updating fetchBooks in api-client.js

The fetchBooks function needs to accept and use the signal.

Code for api-client.js

// api-client.js - before using AbortController
const BASE_URL = 'https://www.googleapis.com/books/v1'

export const fetchBooks = async (query) => {
  try {
    const response = await fetch(`${BASE_URL}/volumes?q=${query}`)
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }
    const data = await response.json()
    return data.items || []
  } catch (error) {
    console.error('Error fetching books:', error)
    throw error // Re-throw the error for the caller to handle
  }
}
// api-client-signal.js - after using AbortController
const BASE_URL = 'https://www.googleapis.com/books/v1'

export const fetchBooks = async (query, signal) => {
  try {
    const response = await fetch(`${BASE_URL}/volumes?q=${query}`, { signal })
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }
    const data = await response.json()
    return data.items || []
  } catch (error) {
    if (error.name === 'AbortError') {
      console.log('Request aborted')
    } else {
      throw error
    }
  }
}
```

Step 4. Refactoring AppBookShelf.jsx

Use the updated useBooks hook with the new AbortController functionality.

Key Changes

  1. Loading State:

    • Show a loading message while books are being fetched.

  2. Error Handling:

    • Display errors if the request fails.

Updated Render Logic

javascript코드 복사{loading ? (
  <p className="text-center">Loading...</p>
) : error ? (
  <p className="text-center text-danger">Error: {error}</p>
) : (
  <BookList books={books} query={query} />
)}

Step 5. Benefits of Using AbortController

  1. Prevent Memory Leaks:

    • Cancels unnecessary network requests when the component unmounts or the query changes rapidly.

  2. Improved Performance:

    • Avoids overlapping network requests.

  3. Cleaner Code:

    • Handles asynchronous requests more effectively with the useEffect cleanup function.


Google BookShelf React App v2 : Result with AbortController

This implementation efficiently manages network activities, ensures smooth application performance, and prevents unnecessary resource usage.

PreviousLesson 7 - Creating Custom Hooks - useBooks and api-clientNextLesson 9 - Show Book Details in a Modal - Working

Last updated 5 months ago