ReviseAlgo Logo

Data Fetching

Fetch API

Master React data fetching with the native Fetch API, covering status states, request cleanups, race conditions, and AbortController.

Last Updated: July 15, 2026 12 min read

1. Learning Objectives

In this lesson, you will learn how to sync components with external APIs using the native Fetch API. By the end of this topic, you will be able to:

  • Perform GET and POST requests inside a component's useEffect Hook.
  • Manage loading, success, and error states to build robust UIs.
  • Identify and resolve "race conditions" in data fetching.
  • Use AbortController to cancel ongoing HTTP requests.
  • Prevent memory leaks caused by updating state on unmounted components.

2. Overview

The native **Fetch API** is the browser standard for making network requests. In React, data fetching is usually initiated inside a useEffect Hook. To build a robust user experience, components must track loading and error states while cleaning up pending requests when parameters change or the component unmounts.

3. Why This Topic Matters

Handling network request lifecycles correctly prevents critical UI bugs:

  • The Race Condition Bug: If a user clicks quickly between options (like User A, then User B), two network requests are sent. If the request for User A takes longer and resolves *after* User B, the screen will display User A's data, even though User B is selected. Cleanups prevent this.
  • Unmounted State Updates: If a network request resolves after a component has unmounted, trying to update the component's state triggers a memory leak and console warnings.

4. Real-World Analogy

Think of data fetching cleanups like **canceling a restaurant order**:

  • Without Cleanup (Race Condition): You order a pizza (Request 1), then quickly change your mind and order a burger (Request 2). Because there is no cleanup, the kitchen prepares both. The pizza arrives 30 minutes after your burger, overwriting your dinner.
  • With Cleanup (AbortController): You order the pizza, then change your mind. You immediately tell the waiter to cancel the pizza order (abort Request 1) and prepare the burger instead. You only receive the burger, avoiding waste.

5. Core Concepts

Below is a comparison of cleanups using Boolean Flags and AbortControllers:

Property Boolean Flag Cleanup AbortController API Cleanup (Recommended)
Mechanism Uses a local variable (e.g. active = false) in the effect cleanup. Uses the browser's native AbortController to cancel the request.
Network behavior The request runs to completion; the component simply ignores the resolved data. The browser cancels the network request immediately, saving bandwidth.
Implementation Complexity Low. Requires a single boolean check. Medium. Requires instantiating a controller and passing a signal.

6. Syntax & API Reference

This example shows how to configure a fetch call with an AbortController:

7. Visual Diagram

This diagram displays how a race condition occurs and how an AbortController resolves it:

8. Live Example — Full Working Code

Below is a complete HTML page demonstrating safe data fetching with loading indicators and abort cleanups:

What just happened? Clicking "Next" quickly aborts the previous network request and starts a new one immediately. Check the browser console to see `Fetch for user #X aborted.` logs. The AbortController prevents race conditions by canceling stale requests, ensuring that the component only renders data matching the active user ID.

9. Interactive Playground

Try It Yourself Challenges:

  1. Comment out the controller.abort() statement in the cleanup function, change the network speed to "Slow 3G" in devtools, click next quickly, and verify that intermediate user names flash on the screen.
  2. Modify the fetch call to perform a POST request that sends a new mock user object to the API.

10. Common Mistakes

Mistake Why it happens Wrong Correct
Omitting a cleanup mechanism for network requests If you do not abort or ignore requests in the cleanup function, responses can resolve in arbitrary order. This can cause race conditions and trigger state updates on unmounted components, leading to memory leaks. useEffect(() => {
fetch(url).then(r => r.json()).then(setData);
}, [url])
(no cleanup)
Instantiate an AbortController, pass its signal to fetch, and call controller.abort() in the cleanup function.
Assuming fetch checks throw on HTTP error status codes The native fetch() function only rejects the promise on network failures (e.g. no internet connection). It does not reject on HTTP error statuses (like 404 Not Found or 500 Server Error). You must check the response status manually. fetch(url).catch(err => setError(err)) (misses 404/500 errors) fetch(url).then(res => {
if (!res.ok) throw new Error('API Error');
return res.json();
})

11. Best Practices

  • Always check res.ok: Check the ok property on response objects to handle HTTP errors (like 404 or 500 status codes).
  • Always clean up requests: Use `AbortController` (or a boolean flag) to cancel pending requests on parameter changes or unmounts, preventing race conditions and memory leaks.
  • Track request states explicitly: Maintain separate states for `loading`, `error`, and `data` to handle all possible request lifecycles.
  • Extract API logic: Move raw fetch code out of components and into separate helper modules or custom hooks (like `useFetch`) to keep components clean.

12. Browser Compatibility/Requirements

The Fetch API and `AbortController` are supported in all modern browsers.

13. Interview Questions

Q1: How do race conditions occur in React data fetching, and how does AbortController resolve them?

Answer: A race condition occurs when multiple async requests are sent in quick succession, and their responses resolve in a different order than they were sent. If a previous request resolves after a later request, the screen will display stale data. Passing an `AbortController` signal to the `fetch` call allows us to cancel the previous request immediately when the component re-renders or unmounts, ensuring that only the latest request's response updates the UI.

Q2: Does native `fetch` throw an exception on 404 or 500 error status codes? How should you handle these statuses?

Answer: No, native `fetch` does not reject the promise on HTTP error status codes (like 404 or 500); it only rejects on physical network failures (like loss of connection). To handle HTTP errors, you must check the response status manually using the `res.ok` boolean property, throwing a manual error if `res.ok` is false: `if (!res.ok) throw new Error('HTTP Error');`

14. Debugging Exercise

Identify why this component throws "Can't perform a React state update on an unmounted component" errors in testing console logs:

View Solution

Diagnosis: The effect does not include a cleanup mechanism. If the user navigates away and the component unmounts before the fetch request resolves, the promise's callback executes setImg on the unmounted component, triggering a memory leak warning.

Fix: Use a boolean flag or an AbortController to prevent state updates after unmounting:

15. Practice Exercises

Exercise 1: Create a search input fetcher

Build a component named SearchFetcher. As the user types in an input field, fetch matching results from an API. Use an AbortController to cancel previous search requests as the user continues typing.

16. Scenario-Based Challenge

The Multi-Step Checkout Payment Sync Controller:

You are designing a checkout wizard. Clicking "Submit Payment" calls a payment processing API. If the user navigates away or closes the tab during processing, you must handle the network lifecycle carefully to avoid duplicate transactions. Describe how you would configure the native fetch calls and cleanups to handle this scenario.

17. Quick Quiz

Q1: What name property is set on errors caught when an HTTP request is aborted?

A) CancelError

B) AbortError

C) NetworkError

Answer: B — When an HTTP request is canceled using AbortController, the promise rejects with an error whose name property is 'AbortError'.

18. Summary & Key Takeaways

  • In React, native Fetch API calls are initiated inside useEffect Hooks.
  • Always track loading, success, and error states explicitly to build responsive UIs.
  • Use AbortController to cancel pending network requests, preventing race conditions and memory leaks.
  • Validate responses using `res.ok`, as native `fetch` does not throw errors on 404 or 500 status codes.

19. Cheat Sheet

Fetch API Element Purpose
const controller = new AbortController(); Creates an AbortController instance to cancel requests.
fetch(url, { signal: controller.signal }) Associates the abort signal with the fetch request.
controller.abort(); Aborts the network request, rejecting the promise with an `AbortError`.
---