trojanowski / react-apollo-hooks

Use Apollo Client as React hooks
MIT License
2.41k stars 109 forks source link

useQuery with suspend=false does not keep polling after error #19

Open wilcoschoneveld opened 5 years ago

wilcoschoneveld commented 5 years ago

Trying to run the following code:

const Status: React.FunctionComponent = () => {
    const { data, errors } = useQuery(STATUS_QUERY, { suspend: false, pollInterval: 2000 });

    console.log(data);
    console.log(errors);

    if (errors && errors.length > 0) {
        return <WarningIcon fontSize="large" />;
    }

    return null;
};

When the query fails (e.g. when server is down) it stops polling.

Unhandled error Network error: Failed to fetch Error: Network error: Failed to fetch at new ApolloError

With react-apollo's Query component I can keep polling.

Let me know if you need more info

wilcoschoneveld commented 5 years ago

I dug into this a little deeper and apparently it's a little complicated with the way how apollo-client implements the ObservableQuery.

The way to solve it is to re-subscribe to the ObservableQuery on error, since apollo leaves the subscription in a terminated state. Not sure if you want to include an extra layer of complexity in this package. Let me know what you think

see: https://github.com/apollographql/react-apollo/pull/1531 https://github.com/apollographql/react-apollo/pull/1580

trojanowski commented 5 years ago

Hi @wilcoschoneveld, thanks for the report.

The way to solve it is to re-subscribe to the ObservableQuery on error, since apollo leaves the subscription in a terminated state. Not sure if you want to include an extra layer of complexity in this package. Let me know what you think

Sure. I think it's a good idea (of course it would be better if solved directly in apollo-client but we could have fix for that in react-apollo-hooks until then).

gunar commented 5 years ago

Would this do it?

if (error) {
  startPolling(INTERVAL);
  return (<p>Error</p>);
}

Edit: It does not work.

wilcoschoneveld commented 5 years ago

@gunar I ended up manually polling with setInterval() and client.query()

si4dev commented 5 years ago

I've noticed that the networkStatus return from useQuery() will remain 8 (=error) and due to that it will stop fetching. It will not stop polling however looking in the code of QueryManager.ts you will see that poll() will call maybeFetch() and that will only fetch when not checkInFlight() and here it will stop fetching due to networkStatus=8.

I don't have a solution and so far I think this is the root cause that polling will not fetch after an error.

EDIT: reviewing the checkInFlight() of QueryManager.ts again looks like it should return false and keep fetching so I'm confused and could be wrong here.

EDIT2: Indeed I was wrong. The useQuery() will stop polling completely on an error. While the module remains polling.

EDIT3: Investigation the Query module (which keeps polling so it works properly) from react-apollo I found out that this one uses also useQuery. However it imports it from @apollo/react-hooks while I was using the react-apollo-hooks package. I've switched to @apollo/react-hooks and now it keeps polling after / during errors. For me this solved my situation.