useQuery data is not updated after retrying the query due to an networkError

I have a useQuery hook inside my component to get a list of people:

const { data, loading, error } = useQuery(GET_PEOPLE_LIST, {
    fetchPolicy: 'cache-and-network',
})

Sometimes when I run this query my token may be expired and the apollo onError link is triggered to refresh the token and rerun the failed query:

const errorLink = onError(({ networkError, graphQLErrors, operation, forward }) => {
  if (networkError && networkError.statusCode === 401) {
    return fromPromise(refreshtoken()).flatMap(response => {
      saveAccessToken(response.accessToken)
      return forward(operation)
    })
  }

  console.error(graphQLErrors)
})

In the network tab I can see that the first query failed with a status of 401, then a request for a new token is made and then the first query is executed again but at this moment the status is 200 and the list of people has been returned.

The problem is getting the data returned by this query. When I give console.log in the data, loading and error of this query I only get the values ​​of the time that failed even though the new attempt was successful and returned the list of people correctly.

const { data, loading, error } = useQuery(GET_PEOPLE_LIST)
console.log({ data, loading, error })

Screenshot 2023-12-19 at 11.54.19

How can I get useQuery values ​​to update after retrying a failed query?

(React 17, @apollo/client 3.6.6)

I already tried returning a new Observable inside onError link, and also the RetryLink suggested in this answer, but no success. I also tried with the latest versions of @apollo/client.

Hi @bnbs :wave: welcome to the Forum! Can you tell me more about how you implemented RetryLink when debugging? For your use case I wouldn’t recommend using onError but RetryLink does seem like the right tool for the job.

Hey, thanks :slight_smile:

When I tested using RetryLink instead of onError, I did something like this:

const retryLink = new RetryLink({
  attempts: {
    max: 2,
    retryIf: async (error, operation) => {
      if (!error) return false
      await refreshToken()
      return true
    }
  }
})

With this approach I also saw, in the network tab, that my first request failed, then a request for a new token was made and then the first request was sent again and returned with the correct data, but const {data} = useQuery(GET_PEOPLE_LIST) was not updated :confused:

Sorry, just saw your reply! Yeah, this is a head-scratcher. There’s nothing in your implementation that jumps out as a problem. Have you set errorPolicy: "all"?

Hi @bnbs, have you found a way to update the data?

Sorry for the delay in responding, but I managed to do it another way. I decided to check if the token has expired and update it before making a request so this way I won’t have the situation I described above.

1 Like