-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useLazyQuery Uncaught (in promise)DOMException: signal is aborted without reason #10520
Comments
Hey @q234876317 👋! The code you're looking at fixed an issue where unmounting a component with an in-flight request caused that promise to hang indefinitely (#10365). The I'll note that we do "catch" this error in a way that avoids uncaught promise warnings, but we float it so that errors are still propagated to the user. One of the biggest reasons I chose not to handle the aborted error in To illustrate this point, let's say Apollo Client updated // https://github.com/apollographql/apollo-client/blob/015a1ffff3febe4604956f4bb137a3111f3d8257/src/react/hooks/useLazyQuery.ts#L95-L107
const promise = internalState
.asyncUpdate(controller.signal)
.then(queryResult => {
abortControllersRef.current.delete(controller);
return Object.assign(queryResult, eagerMethods);
});
promise.catch(() => {
abortControllersRef.current.delete(controller);
});
return promise.catch((error) => {
// Do nothing if we are catching an abort, otherwise re-throw to avoid swallowing errors
if (e.name !== 'AbortError') {
throw error;
}
}); In this case, because const [execute] = useLazyQuery(QUERY);
try {
const result = await execute();
if (typeof result !== 'undefined') {
const { data } = result;
// do something with `data`
}
} catch (e) {
// deal with a non-aborted error
} I find this adds significantly more noise to the success handling code than if we let the user decide how to handle aborted errors. By rejecting the promise, I find this fits the mental model as well. A component that unmounts while a query is fetched truly is exceptional! We aren't expected to get a successful result because the component isn't around to do anything with it. We'd rather you deal with this in a way that makes the most sense for your app. Perhaps unmounting while fetching actually does mean something in your app that might not in others. Instead, if you want to ignore this error, wrap the returned promise in a try/catch and check for const [execute] = useLazyQuery(QUERY);
try {
await execute();
} catch (error) {
if (error.name !== 'AbortError') {
// handle the non-abort error in some way
}
} |
well done, thanks a lot! |
Hello, I have also the same issue after upgrading the The bug was introduced with version Here is the stack trace for reference:
@jerelmiller you have merged PR #10427 but it doesn't seem to fix the issue (if it's the same). |
I'm also having an issue here, and don't fully understand how this is marked resolved. In my tests, using This seems to be because of React v18's So I don't see how there's anyway to use
I'm not sure, seems to happen all the time with latest React v18 and Surely we don't want to wrap everything in I know I could probably create my own version of So I'll either do that, or downgraded to But just trying to understand whether this really is intended behaviour or not for React 18 and |
agree with @asgeo1 . I have this issue too. It fires not when there's a query running, but every time I have a component with |
@asgeo1 I'm curious, how are you executing the query in strict mode? What you describe seems to imply that you're executing the query in a That being said, there are some legitimate cases for why this behavior is not ideal. I am considering a different approach that will instead let the promise resolve, but if the component is unmounted, the value will just disappear into the void (i.e. we won't try and update state). I think this would help in this situation. |
@jerelmiller in our project we use import { useLazyQuery } from '@apollo/client';
import { GET_USERS } from './query';
interface QueryData {
users: User[];
}
interface QueryVars {
sortBy: string;
query: Pick<UserQueryInput, '_partition'>;
}
function useFetchUsers() {
const [execute, { loading, error, data, refetch, called }] = useLazyQuery<QueryData, QueryVars>(
GET_USERS,
{
notifyOnNetworkStatusChange: true,
},
);
const fetchUsers = async (sortBy?: SortBy) => {
const query: QueryVars = {
query: { ... },
sortBy,
};
const response = called
? await refetch(query)
: await execute({
variables: query,
});
return response.data?.users || [];
};
return { fetchUsers, loading, error, users: data?.users || [] };
}
export default useFetchUsers; function Users() {
const { fetchUsers, users, loading, error } = useFetchUsers();
const [sortModel, setSortModel] = useState<GridSortModel>(defaultSortModel);
const handleReload = () => {
fetchUsers(sortModel[0] as SortBy);
};
useEffect(() => {
if (!loading) {
handleReload();
}
}, [users]);
return (
<Fragment>
<button onClick={handleReload}>Reload</button>
<UsersTable users={users} loading={loading} />
</Fragment>
);
}
export default Users; |
I have the same problem in production so strict mode may not be the culprit. I have two types of AbortError:
|
So the reason why this is kept "Closed" is because this is not considered a Bug by the team? Just asking so that I know how to manage codes |
For me, it's a bug AND a breaking change. A minor version upgrade should not cause something as important! |
I agree with @guicara . This is why I was asking the reason for this issue being market as "Closed" |
What are the next steps @jerelmiller? |
@70nyIT I've kept this closed because I'm going to track this in #10533 which is a pretty compelling case to change the behavior. I'd recommend following that issue to keep track of updates. @guicara As mentioned in #10520 (comment), I'm planning on changing the behavior. We've got this issue queued up for us to look at, so it will get some attention in the near term. |
I've changed my mind. I'm going to reopen this issue so that I can tag it in my PR. This will close again when the PR is merged. |
Hey all 👋 We just released v3.7.11 that contains a change to the behavior of |
Confirmed working as expected! Thanks @jerelmiller |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Uncaught (in promise)DOMException: signal is aborted without reason
these below code maybe cause the exception,can we catch the exception?
The text was updated successfully, but these errors were encountered: