apollo-client: Network-only refetch after network error does not update networkStatus

Versions

  • apollo-client@1.0.4
  • react-apollo@1.0.1

NOTE: this needs a seperate backend grpahql server to re-create so I have not created a react-apollo-error-template repo.

Intended outcome: Refetching a query after network error should always update loading to true and networkStatus to 4 - until either success or error happens.

Actual outcome: NetworkStatus remains at 8 and loading remains set to false on refetch. Only once server is up again and refetch completes susseccfully does networkStatus update to 7, and loading remains false the entire time.

How to reproduce the issue:

  • Create a simple component with a query and options of fetchPolicy: 'network-only', notifyOnNetworkStatusChange: true.
  • Have your component render a loading… text if loading is true.
  • Have your component render a refetch button<a onClick={() => refetch()>Try again</a> if error is true.
  • turn off your API server that has the graphql endpoint and load your component, it should render loading and then error states.
  • Click your refetch button a few times.
  • Turn back on your server.
  • Click refetch button again.
  • Note that networkStatus is staying on 8.

Related issues See https://github.com/apollographql/react-apollo/issues/642

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 11
  • Comments: 38 (10 by maintainers)

Most upvoted comments

Hey! This is still an important and open issue!

This issue has been automatically closed because it has not had recent activity after being marked as stale. If you belive this issue is still a problem or should be reopened, please reopen it! Thank you for your contributions to Apollo Client!

Confirmed that its broken in 2.1.3, sigh…

Unfortunately, in my case even after update to apollo-client@2.4.2 and react-apollo@2.1.11 triggering refetch() still doesn’t set loading to true (I’m using network-only fetchPolicy). I will try to provide some example soon.

EDIT: Sorry I just didn’t know that notifyOnNetworkStatusChange={true} is required to toggle loading state.

Everything works as expected 😃

For anyone looking for the refetch workaround:

import React, { Component } from 'react'
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'

class SomeComponent extends Component {

  state = { refetching: false }

  refetch = (): void => {
    this.setState({ refetching: true })
    this.props.refetch()
      .then(() => { this.setState({ refetching: false }) })
      .catch(() => { this.setState({ refetching: false }) })
  }

  render() {
    const { data: { loading, error, viewer } } = this.props
    const { refetching } = this.state

    if (loading || refetching) {
      return (<div>loading..</div>)
    } else if (error) {
      return (
        <div>
          <p>Error</p>
          <a onClick={this.refetch}>Retry</a>
        </div>
      )
    } else {
      return (<div>Name: {viewer.name}</div>)
    }

  }
}

const Viewer = gql`
  query Viewer {
    viewer {
      name
      uuid
    }
  }
`

export default graphql(Viewer, {
  options: {
    fetchPolicy: 'network-only',
    notifyOnNetworkStatusChange: true,
  },
})(SomeComponent)

Still happening for me in apollo-client 2.0.1

@helfer currently network errors crash the app in that they can’t be caught, and they remove the query from the store making it impossible to refresh. Transient network errors are sure to happen from time to time. Is there any reason that an uncaught network or graphql error should put the app into an unrecoverable state?

I’m going to add this to the post 2.0 bug milestone to make sure it is prioritized and fixed for everyone! Sorry for the delay!

I have the same problem with : “apollo-client”: “^2.2.5”, “react-apollo”: “2.0.0”,

Problem

this.props.data.refetch() is not updating the render props after an network error (http 401 unauthorized)

Demo

Here is a demo based on the react-apollo-error-template and starts a minimal node server to simulate the network errors: https://github.com/aheissenberger/react-apollo-error-401

This problem is a duplicate of https://github.com/apollographql/apollo-client/issues/2513

installing yarn add react-apollo@^2.1.0-beta.2 fixed the problem

I’m seeing similar issues with react-apollo @2.0.4 in my react-native app. I’ve created an issue on Stack Overflow, that I’d love to get some eyeballs on. https://stackoverflow.com/questions/48440527/how-to-refresh-component-data-with-apollo-refetch-data

Sounds like my expected results are valid…

  • refetch causes networkStatus to be reset from 8 to 4 (e.g. refetching)
  • refetch causes data.loading to be true
  • refetch automatically refreshes props.data with successful results or new errors

It also sounds like some of you are seeing your props.data refreshing. I’ll check out apollo-link-retry as suggested @adambom above

However, I’m not having any luck refreshing the props.data so far, nor am I seeing any change to the data.error.message or data.networkStatus

UPDATE: While super interesting and also useful, apollo-link-retry turned out not to be the solution to my problem. I will use it though to smooth out the rough edges when network status is flaky.

I think they version all their libraries differently: apollo-client has been at 2.0 for a while but the link packages are mostly still at 1.x. Here’s the release I’m talking about: https://github.com/apollographql/apollo-link/releases/tag/apollo-link-retry%402.0.0

I’m not doing anything too different from the documentation example. If you just follow the example here you should get the behavior I’m describing.

That said, I’ve customized the behavior a little bit. I don’t want network errors to crash the app, so I’ve prevented it from doing so by forcing apollo to retry on network errors forever. Graphql errors will still be handled the normal way, but here’s what I’ve done:

export const errorBus = new EventEmitter();

const withRetries = new RetryLink({
  delay: {
    max: 30 * 1000,
  },
  attempts: (count, operation, error) => {
    console.log(`Retrying operation ${operation.operationName} (Attempt ${count})`);

    if (!!error) {
      errorBus.emit('error', error);
    }
    return !!error;
  }
});

const httpLink = new HttpLink({ uri: [Config.GRAPHQL_URI, 'graphql'].join('/') });

const errorHandler = onError(options => {
  errorBus.emit('error', options);
});

let link = ApolloLink.from([
  errorHandler,
  withRetries,
  httpLink,
]);

export const client = new ApolloClient({
  link,
  cache: new InMemoryCache(),
});

So the idea here is that if there’s ever a network error (RetryLink ignores GraphqlErrors for some reason - by design) we just keep retrying. You could could program it to give up at some point, if you wanted, but in the event of a network error, I’m assuming it’s because of bad connectivity and I want to reconnect at some point in the future. To notify any components that an error has occured, I create an EventEmitter and emit events. Anyone who cares there’s been an error can subscribe to that emitter.

this Error is happing in 2.0.4 , it’s very simple to test in network-only, turn off the server , and navigate page and when those pages give error, turn on the server, and try again, the props.query.error value keeps … with the error, despite apollo is calling the page and on the network tab , data is sent from the server to the client, the problem that data is not loading… how I can help, in where code i can look for ?

Like @jay1337 mentioned, this bug appears to be worse in apollo-client@2.0.3. The networkStatus and error are never updated after a successful refetch.

This happens with the default network policy as well.

It’s not just network errors either, graphql errors have the same problem. Only difference is their networkStatus is always 7 (as opposed to 8 for network errors).

@jbaxleyiii Looks like i fill issue with same problem in react-apollo issue. I put investigation result and reproduction steps in last sections of bugreport

@jbaxleyiii : here are some precisions.

I work on a React Native project with:

  • apollo-cache-inmemory@0.2.0-beta.2
  • apollo-client@2.0.0-beta.2
  • apollo-link@0.6.1-beta.4
  • apollo-link-http@0.6.1-beta.4
  • apollo-link-set-context@0.6.1-beta.1

I have a component “connected” using graphql HOC. I have a setInterval to trigger a refetch of the query. If a refetch fails, then the data.error remains, even if a refetch has succeeded after the fail.

Is it enough information for your to have a look at this issue ?