React: AbortController Race Conditions
Dennis Maina
Dennis Maina

Published on 20th October, 2022 (11 months ago) ● Updated on 20th October, 2022

React: AbortController Race Conditions

(5 minutes read)

Using AbortController to deal with Race Conditions in React

When developing applications, data fetching is one of the most fundamental tasks. Despite that, there are some things to watch out for: one of them is race conditions. This article explains what they are and provides a solution using the AbortController.

Identifying a race condition

A “race condition” is when our application depends on a sequence of events, but their order is uncontrollable. For example, this might occur with asynchronous code.

Here's an example using React and React router by defining the route and render the  component.

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Post from './Post';
 
function App() {
  return (
    
      } />
    
  );
}
 
export default App;

In the  component, we either display a loading indicator or the fetched data. The most important part takes place in the  hook.

If you want to know more about the  hook, check out React: How to Make API Calls Using the useEffect Hook

Above, we fetch a post based on the URL. So, if the user visits , we send a GET request to .

Defining the race condition

The above approach is very common, but there is a catch. Let’s consider the following situation:

    • The user opens  to see the first post,
      • we start fetching the post with id ,
      • there are some Internet connection issues,
      • the post does not load yet,
    • Not waiting for the first post, the user changes the page to 
      • we start fetching the post with id ,
      • the post loads without issues and is available almost immediately,
    • The first post finishes loading,
      • the  line executes, overwriting the current state with the first post,
      • even though the user switched the page to , the first post is still visible.

Unfortunately, we can’t cancel a promise once we create it. There was a proposal to implement a feature like that, but it has been withdrawn.

The most straightforward fix for the above issue is introducing a  variable, as suggested by Dan Abramov. When doing that, we need to use the fact that we can clean up after our  hook. React will call it when our component unmounts if  returns a function.

Now, the bug we’ve seen before is no longer appearing:

    • The user opens  to see the first post,
      • we start fetching the post with id ,
    • Not waiting for the first post, the user changes the page to ,
      • the  cleans after the previous post and sets  to true,
      • we start fetching the post with id ,
      • the post loads without issues and is available almost immediately,
    • The first post finishes loading,
      • the  line does not execute because of the  variable.

Now, if the user changes the route from  to , we set  to . Thanks to that, if the promise resolves when we no longer need it, the  is not called.

Introducing AbortController

While the above solution fixes the problem, it is not optimal. The browser still waits for the HTTP request to finish but ignores its result. To improve this, we can use the AbortController.

With it, we can abort one or more fetch requests. To do this, we need to create an instance of the AbortController and use it when making the fetch request.

Above, we pass the  through the fetch options. Thanks to that, the browser can stop the request when we call .

We can pass the same  to multiple fetch requests. If we do that,  aborts multiple requests.

The above also fixes the issue we’ve had with the race conditions.

    • The user opens  to see the first post,
      • we start fetching the post with id ,
    • Not waiting for the first post, the user changes the page to ,
      • the  cleans after the previous post and runs ,
      • we start fetching the post with id ,
      • the post loads without issues and is available almost immediately,
    • The first post never finishes loading because we’ve already aborted the first request.

We can observe the above behavior in the network tab in the developer tools.

A crucial thing about calling the  is that it causes the fetch promise to be rejected. It might result in an uncaught error.

To avoid the above message, let’s catch the error.


Comments (0)

Dennis Maina

Dennis Maina

https://dentricedev.com

CEO and Founder of DentriceDev Solutions.

18

Articles

July '22

Joined date

Domain Name Registration & Hosting
Domain Name Registration & Hosting

HostPinnacle Kenya is the best and cheapest web hosting company in Kenya with world-class web hosting packages and affordable web design offers. Apart from that we offer free life-time SSL certificate, affordable domain registration in Kenya and free whois privacy. We have an award-winning support team available 24/7/365 to help you with your queries.

Do you want to write with us? Register and start blogging.

Register Login

Thank you for your support!

We deliver the best web products