Skip to content
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

onError and onCompleted callbacks do not work in useQuery hook #8313

Open
Tracked by #8596
jokerosky opened this issue May 28, 2021 · 19 comments
Open
Tracked by #8596

onError and onCompleted callbacks do not work in useQuery hook #8313

jokerosky opened this issue May 28, 2021 · 19 comments
Labels
🔍 investigate Investigate further

Comments

@jokerosky
Copy link

jokerosky commented May 28, 2021

Intended outcome:
onCompleted or onErorr callbacks should be called on refetch or polling in useQuery hook, according to the documentation https://www.apollographql.com/docs/react/api/react/hooks/

Actual outcome:
onCompleted called only once at initial render, onErorr not called

How to reproduce the issue:

  1. Reload the page, notice that there is 'completed' word in browser developer console

  2. wait for 10 seconds according to the pollInterval

  3. notice that there is a new network request, but no console output

  4. click 'Refetch' button to explicitly call refetch function

  5. set network to offline mode in browser developer tools, wait for 10 seconds or click refetch button and see that no onError callback fired.

import ReactDOM from 'react-dom';

import { ApolloClient, ApolloProvider, gql, InMemoryCache, useQuery } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://48p1r2roz4.sse.codesandbox.io',
  cache: new InMemoryCache()
});

const QUERY = gql`
query GetRates {
  rates(currency: "USD") {
    currency
    rate
  }
}
`

function App() {
  const [count, setCount] = useState(0);

  const { refetch, data } = useQuery(QUERY, {
    fetchPolicy:'network-only',
    pollInterval: 10 * 1000,
    onCompleted: () => {
      setCount(count+1);
      console.log('completed')
    },
    onError: () => {
      setCount(count+1);
      console.log('error')
    },
  })
  
  const clickCallback = useCallback(()=>{
    refetch();
  }, [refetch]);

  return (
    <div className="App">
      Apollo callbacks count  {count}

      <button onClick={clickCallback}>Refetch</button>
      <div>{JSON.stringify(data)}</div>
    </div>
  );
}


ReactDOM.render(
  <React.StrictMode>
   <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  </React.StrictMode>,
  document.getElementById('root')
);

Versions

"dependencies": {
"@apollo/client": "^3.3.19",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"graphql": "^15.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},

@jokerosky
Copy link
Author

I've tried change the version of @apollo/client to older one like 3.3.6, and the problem remains, maybe I did not understand the documentation, or something broken after upgrade to React 17?

@dylanwulf
Copy link
Contributor

dylanwulf commented May 28, 2021

possible duplicate of #5531. That issue doesn't mention onError though

@alanxp
Copy link

alanxp commented May 30, 2021

I thought i was the only one with this problem!,

the "onError" callback only shows this
{"graphQLErrors":[],"networkError":{},"message":"Failed to fetch"}

and it wont let me know if it's a networkError or graphQLErrors because both Object and Array are Empty!

@jokerosky
Copy link
Author

I thought i was the only one with this problem!,

the "onError" callback only shows this
{"graphQLErrors":[],"networkError":{},"message":"Failed to fetch"}

and it wont let me know if it's a networkError or graphQLErrors because both Object and Array are Empty!

I suppose it is normal behavior, the problem for me is that onError or onCompleted have not called after first rendering.

@alanxp
Copy link

alanxp commented May 31, 2021

I thought i was the only one with this problem!,

the "onError" callback only shows this
{"graphQLErrors":[],"networkError":{},"message":"Failed to fetch"}

and it wont let me know if it's a networkError or graphQLErrors because both Object and Array are Empty!

I suppose it is normal behavior, the problem for me is that onError or onCompleted have not called after first rendering.

How is it supposed to be a normal behavior sending you empty arrays and o bjects when in the documentation says it coule throw either of those?

@ilya-bmi
Copy link

ilya-bmi commented Jun 8, 2021

Same here. onError doesn't fire on error. It keeps sending retrying requests to the server indefinitely.

@brainkim brainkim self-assigned this Jul 7, 2021
@twc3
Copy link

twc3 commented Jul 14, 2021

I recently noticed that onError was not working for me on newer versions both with useQuery and useMutation, but reverting to 3.3.6 'fixed' it for me.

In our case, onError was no longer firing when network errors such as a 401 occurred, which is how we caught it.

@jp928
Copy link

jp928 commented Aug 1, 2021

Same here.

Polling is not triggering onCompleted anymore. Tested on apollo-client 3.4.1 with React 17

@brainkim
Copy link
Contributor

brainkim commented Aug 2, 2021

One thought. The code which calls the onCompleted and onError callbacks has some logic which prevents it from being called when Apollo determines that the results are the same, which is why polling/refetching might not call the function, insofar as the majority of polling/refetching calls will usually result in the same data.

if (
this.previousOptions &&
!this.previous.loading &&
equal(this.previousOptions.query, query) &&
equal(this.previousOptions.variables, variables)
) {
return;
}

Is this behavior surprising to y’all? Is that the source of the bugs in this issue?

cc @benjamn

@jokerosky
Copy link
Author

jokerosky commented Aug 2, 2021

for me it didn't work even when result of query was different (but i'm not sure, have to recheck this).
Surprise was in that the code written year ago stopped work, althoug that section was written even before (2 years ago).
or maybe I miss something from the documentation.

@dylanwulf
Copy link
Contributor

dylanwulf commented Aug 2, 2021

@brainkim @jokerosky I have a runnable reproduction over in #5531 (comment) showing that onCompleted isn't being called when the results of a polling query are different. It's still on v3.3, I haven't checked v3.4 yet.

@brainkim brainkim mentioned this issue Aug 13, 2021
14 tasks
@3pns
Copy link

3pns commented Oct 25, 2021

It does not work for me as well, it seems like this is an old issue : apollographql/react-apollo#3709

@tonycassara
Copy link

Hi I'm also having this issue here, onCompleted is called on the first query but subsequent polling does not call onCompleted. Also onError does not get called when status code 502 is found (should be networkError). I'm on "@apollo/client": "3.3.11"

@tonycassara
Copy link

Using a useEffect workaround for now but it's not ideal because my onCompleted and onError methods are not being passed directly to the query.

@tonycassara
Copy link

tonycassara commented Oct 26, 2021

Confirming that apollographql/react-apollo#3709 (comment) solved my issue. This should be more clear in the docs. Might open a PR later.

@sbsupper
Copy link

sbsupper commented Dec 7, 2021

Confirming that apollographql/react-apollo#3709 (comment) solved my issue. This should be more clear in the docs. Might open a PR later.

i don't think so
it just make query throw network everytime but cache

@benderillo
Copy link

benderillo commented Aug 22, 2022

Confirming that apollographql/react-apollo#3709 (comment) solved my issue. This should be more clear in the docs. Might open a PR later.

This should not be suggested as a workaround. This only works if the fetch policy is set to "network-only" which is not suitable for many use cases.
The solution should be working for any fetching policy.

@raphaeleidus
Copy link

raphaeleidus commented Nov 29, 2022

you need to set notifyOnNetworkStatusChange: true, on your options for useQuery, then the onComplete and onError will get called for each update not just the first.

POC: https://codesandbox.io/s/keen-browser-7n1oem?file=/src/index.tsx

related docs: https://www.apollographql.com/docs/react/data/queries/#inspecting-loading-states
relavant code:

if (!result.loading) {

@Return-1
Copy link

I can also verify this happens, I was attempting to write some custom retry logic in case the query fails so not triggering onError again after i've called refetch within onError is a problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔍 investigate Investigate further
Projects
None yet
Development

No branches or pull requests