DOMException: signal is aborted without reason in useEffect with async call
Asked Answered
S

3

7

I have a project using React in Strict Mode alongside GraphQL.

I updated some packages, and I now get the following error in useEffect containing async calls.

  useEffect(() => {
    const loadTags = async () => {
      const { data } = await fetchTags();
      setTags([...(data?.tags || [])]);
    };

    loadTags();
  }, [current, fetchTags]);

DOMException: signal is aborted without reason in useEffect with async call.

I am not quite sure what is causing this, I believe the use effect rerun and clear itself up, and it doesn't abort the query properly.

This didn't happen previously, or at least didn't produce an error.

I am wondering if my implementation if incorrect, or if some package I updated go an issue, I couldn't find any relevant thread on github on the package I updated

Sheridansherie answered 26/1, 2023 at 6:53 Comment(0)
R
5

I have also the same issue after upgrading the @apollo/client library from version 3.7.1 to 3.7.8, when using useLazyQuery (probably the same with useQuery).

The bug was introduced with version 3.7.4.

Until a fix is provided by Apollo, the solution is to downgrade to version <= 3.7.3.

Here is the stack trace (for reference):

useLazyQuery.ts:78 Uncaught (in promise) DOMException: signal is aborted without reason
    at http://localhost:3000/node_modules/.vite/deps/@apollo_client.js?v=d5c2e0d9:8702:20
    at Set.forEach (<anonymous>)
    at http://localhost:3000/node_modules/.vite/deps/@apollo_client.js?v=d5c2e0d9:8701:35
    at safelyCallDestroy (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:16737:13)
    at commitHookEffectListUnmount (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:16864:19)
    at invokePassiveEffectUnmountInDEV (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:18359:19)
    at invokeEffectsInDev (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:19697:19)
    at commitDoubleInvokeEffectsInDEV (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:19678:15)
    at flushPassiveEffectsImpl (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:19499:13)
    at flushPassiveEffects (http://localhost:3000/node_modules/.vite/deps/chunk-JZ3YVIXN.js?v=8247418e:19443:22)
Rosefish answered 18/2, 2023 at 21:0 Comment(3)
Do you have link to the issue?Hospitalization
@Hospitalization there is a similar issue here in the Apollo Client GitHub repository.Rosefish
By the way, this issue only happens when StrictMode is enabled. As explained by jerelmiller in above link, a temporary solution is to create a custom hook that extends useLazyQuery, wrap everything in try/catch, and not raise an error for AbortError. However, it's not a great solution. For me, it's clearly a bug and a breaking change because it was working fine with version <= 3.7.3.Rosefish
Q
1

In my case, it is a Next JS project, I set the reactStrictMode of the next.config.js file to false and it ran normally with version 3.7.10

 /** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,
  compiler: {
    styledComponents: true
  },
  eslint: {
    ignoreDuringBuilds: true
  }
}

module.exports = nextConfig
Questionnaire answered 19/9, 2023 at 14:12 Comment(0)
E
1
import { useEffect, useState } from "react";

const useAxios = (url) => {
  const [data, setData] = useState([]);
  const [error, setError] = useState("");

  useEffect(() => {
    let isMounted = true;
    const controller = new AbortController();
    const signal = controller.signal;
    try {
      const fetchData = async () => {
        const res = await fetch(url, {
          method: "GET",
          signal,
        });
        return res.json();
      };

      fetchData()
        .then((data) => {
          isMounted && setData(data);
        })
        .catch((error) => {
          if (error instanceof DOMException && error.name === "AbortError") {
            console.log(error.message);
          } else {
            setError(error.message);
          }
        });
    } catch (error) {
      setError("Inter error occured!");
    }

    return () => {
      isMounted = false;
      controller.abort();
    };
  }, []);

  return [data, error];
};

export default useAxios;
Exurbia answered 1/8 at 4:16 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Pleione

© 2022 - 2024 — McMap. All rights reserved.