apollo-client: Loading never gets updated to "false"

Hi, this is very indeterministic behaviour. But sometimes the loading flag never get updated to true false. I can see that data are correctly received by client in the console. Any idea how can I debug this to report why is it not getting updated?

[EDIT]: I can report that it only happens on queries that return arrays of fields

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 51
  • Comments: 138 (35 by maintainers)

Commits related to this issue

Most upvoted comments

I actually had a really similar issue to this, but I was using react-apollo and my component was getting stuck in “loading=true” state. Turns out the problem was that I hadn’t specified notifyOnNetworkStatusChange=true (by default it’s false). So in the graphql container I had to set { options: { notifyOnNetworkStatusChange: true } }.

Can I get a show of hands for how many people are still seeing this issue or a similar one? Please vote 👍 if you’re having the issue.

If one or more of you could provide a reproduction using the react-apollo-error-template, that would also help us greatly speed up the process of finding and fixing this bug.

In our case the loading flag is not properly updated after calling client.resetStore().

This is very annoying bug, it still happens(

I am having the same issue. It only happens when I perform a second query different from the first that yields the same result as the first.

+1. We have it in our react application as well. What we do to get this strange loading behaviour:

  • Login to portal.
  • Data gets queried and displayed normally.
  • Logout user. --> Component that queried data unmounted, and client.resetStore() is called.
  • Login new user. --> loading in data prop stays true, and no query result returned

I also encountered this bug, and setting notifyOnNetworkStatusChange: true in 1.9.1 didn’t always work (but bug seemed to occur less frequently). Similarly to @AlexMost, downgrading to 1.8.1 solved the issue.

Not sure if it’s related to this issue, but this happens when a react component is “remounted” with different variables for the query. While not standard practice, it happens e.g. when including some content in a component’s state, and the state is updated with new content which happens to be the same component only with different props/variables. In this case a remount occurs.

This line seems to be what’s causing problems (the listener gets removed prematurely):

https://github.com/apollographql/apollo-client/blob/master/src/core/ObservableQuery.ts#L125

This still occurs with the latest version when using composed graphql from react-apollo for a component. I don’t know if this also applies to the related Query apollo-client@2.5.1 react-apollo@2.5.2

As mentioned above, adding notifyOnNetworkStatusChange: true to the options still fixes this issue of data.loading not being set to false in some instances.

    options: () => ({
      errorPolicy: 'all',
      fetchPolicy: 'network-only',
      notifyOnNetworkStatusChange: true,
      ssr: false,
    }),

Still occurring for us as well. Hopefully we’ll be able to make a reproduction…

Any update on this issue, I tried notifyOnNetworkStatusChange: true but it didn’t help, I have container component that is fetching 3 queries, if one has errors then loading never gets updated to false

I can confirm that the issue in dylanscott/apollo-repro appears to be fixed after upgrading to the apollo-client 2.0 beta.

I have exactly the same issue. it only happens sometimes for me if the result will be an empty array.

"dependencies": {
    "apollo-client": "^1.9.2",
    "graphql-tag": "^2.4.2",
    "history": "^4.7.2",
    "html-webpack-plugin": "^2.30.1",
    "idb": "^2.0.3",
    "lodash": "^4.17.4",
    "path": "^0.12.7",
    "react": "^15.6.1",
    "react-apollo": "^1.4.15",
    "react-dom": "^15.6.1",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "semantic-ui-react": "^0.72.0",
    "serviceworker-webpack-plugin": "^0.2.3",
    "webpack": "^3.5.5",
    "webpack-dev-server": "^2.7.1"
}

When I take a look into my browser network console I always get the result like I´ve expected but the loading state of the query sometimes just stays true even when the result is still served.

Also had this issue in apollo-client:1.9.2. This issue was reproducing each time when query returned an empty list as a result. (productsQuery.products was empty). Everything works ok on page reload. Downgrade to 1.8.1 fixed that. Finally solved this issue with notifyOnNetworkStatusChange: true in 1.9.1, but feels like it is a workaround.

Just hit this bug as well. My scenario is very similar to that of @cyrus-za and @oliviertassinari from https://github.com/apollographql/react-apollo/issues/170. I managed to isolate the kinds of updates that result in loading being stuck to true and data not updating; Maybe the following will help someone with more intimate knowledge of Apollo internals track down the bug.

We are using react-apollo 1.4.16 and apollo-client 2.3.5.

Our scenario: We use react router 4 and each page is wrapped in graphql(). When the page mounts, the query is executed with variables supplied to the page. We don’t currently use id-based cache normalization, but the default query path based one.

I isolated 3 conditions that are necessary for it to be stuck:

  1. I navigate away from a page and then back again with a different set of variables supplied to the page.
  2. The query results are the same as those from the previous page visit. If the results are different there is no problem.
  3. There is no other page visit between the two, which returns a different query result. For some reason, if I navigate away, then back, and the resulting query returns a different result than the previous, then even if a subsequent page visit does lead to the same query result as the first one, it works.

Like others have noted before me, the queries execute without errors, the data is in the cache, it is just that when the data is loaded my page is not updated by the graphql() HOC. And notifyOnNetworkStatusChange: true did work for me, probably because it triggers updates to the component even if data loading doesn’t.

For me it seems that in 2.0, after an error (error not null and networkStatus at 8), the status of the request is not updated by a refetch (and the component not rerendered). Even after loading successfully the refetch, the error remains…

Hi, I have another reproducible case.

I have noticed that this happens after I call resetStore. My workflow is:

  1. When logOut -> resetStore
  2. logIn … no component will update to loading = false

To reproduce:

  1. go to: http://staging.claraworld.net
  2. use: t.trescak@westernsydney.edu.au / apollo123 as access data
  3. log out
  4. log back in … voila, everything is stuck on LOADING

Reset store line is in client.min.js:1920

logout() {
        apollo_1.default().resetStore();
        this.profile = null;
        helpers_client_1.RouterUtils.go('/');
    },

And the loading code is client.min.js:11745

if (notificationData.loading || scheduleData.loading) {
        return React.createElement(loading_view_1.default, null);
    }

@helfer I’ve put together a minimal repro of this. I didn’t notice you mentioned the react-apollo-error-template project but hopefully this should be similar enough - my repro was created with create-react-app and is pretty small. You can find it here.

I go into some detail about how to reproduce the issue in the README, but it appears to be caused by some interaction between

  • Using polling with the pollInterval option
  • Having multiple copies of the same GraphQL container component rendered on the page at one time
  • Triggering a re-render on those GraphQL components while a polling request is in flight

Let me know if you have any trouble reproducing this. I tried to make it pretty easy.

I confrim this bug still occurs on npm list --depth=0 | grep apollo |--@apollo/react-hooks@3.1.3 |--@apollo/react-testing@3.1.3 |--apollo-cache-inmemory@1.6.5 |-- apollo-client@2.6.8 |-- apollo-link@1.2.13 |--apollo-link-http@1.5.16 |--apollo-link-retry@2.2.15 |--react-apollo@3.1.3

In my case I add notifyOnNetworkStatusChange solves the issue.

useQuery(getXXXXQuery, { variables: { .... }, notifyOnNetworkStatusChange: true });

I created a minimum possible reproduction scenario here: react-apollo-error-template.

I use react-router-dom v4.2.2 to navigate between pages, apollo-client v1.9.2 and react-apollo v1.4.15.

Steps to reproduce:

  • Start app
  • Go to Logout Page
  • Press Logout button

Logout does client.resetStore() and then history.push('/'). You can then see the Loading... on Home page. If you Press the Home link at the bottom, component does refresh and works ok from then on. If I comment out client.resetStore() on Login page, all works ok.

I have same problem.

  1. When logOut -> resetStore
  2. login
  3. When data == last data … no component will update to loading = false

if data != last data , no problem.

So, I try get server time.

query adminInfoQuery {
  admin {
    id
    username
    realname
    extendsPermission
  }
  serverInfo {
    now
  }
}

Similar for me. I have a component that I mount in when data is required, and it’s often mounted with different variables. Just as @abergenw mentions. The network request succeeds but the component is stuck in loading state.

It takes a further (unrelated) interaction from the user - in my case, tapping on a map elsewhere - to come out of the loading state.

I can get around it rather horribly by setting an interval which updates a sham state parameter regularly with Date.now() until the loading prop turns true.

I’m experiencing the same problem. When I call data.refetch() it sometimes get stuck in loading: true.

@schickling a temp solution for now (unless you are using streaming data) is to check for existence of data in the “data” property, and not the “loading” property. But yes, a systematic solution would be helpful.

Hi, just following up. This is still persistent in 0.10.0 after the brand new batchingnetworkinterface. Can I somehow help? I just don’t know where to start and what to watch for.

Definitely a fan of prioritizing this one 😃 At this point this issue is the historical #1 issue by number of comments for both the apollo-client and react-apollo github projects. I spent a few hours digging into this yesterday, but it’s tough as someone without an intimate knowledge of apollo internals and the apollo-client/react-apollo state machine. I also upgraded to Apollo 2.0 to no avail.

https://github.com/apollographql/react-apollo/issues/976 has a pretty clear repro (which matches my experiences), although I imagine there are other situations where this happens as well.

See https://github.com/apollographql/react-apollo/issues/170, https://github.com/apollographql/react-apollo/issues/976 and a bunch of potential dupes as well: perhaps https://github.com/apollographql/react-apollo/issues/807, https://github.com/apollographql/react-apollo/issues/890, and more. It looks like a previous version of this issue was fixed in https://github.com/apollographql/react-apollo/issues/718, but came back again?

@bradleyayers solution work form me too

Hey guys, we are also experiencing the same issue (logout -> resetStore -> login) on version 1.9.0. However I downgraded the version to 1.8.1 and it seems to work again. I guess some kind of regression introduced in 1.9.0?

I’m also using react-apollo@1.4.10, but changing the version there does not seem to influence the result.

@abergenw This is exactly how we are using components with apollo and are seeing the same behavior as described. Any suggestions on a better, more standard approach?

UPDATE: It helps to check which version you’re on. I discovered this issue was already resolved for my case. I was just a few versions behind. Nothing to see here. Move along…

I will try over the next few days!

Same behavior here.

    "apollo-cache-inmemory": "1.5.1",
    "apollo-client": "2.5.1",
    "apollo-link": "1.2.6",
    "apollo-link-context": "1.0.12",
    "apollo-link-error": "1.1.5",
    "apollo-link-http": "1.5.9",
    "react": "16.8.2",
    "react-apollo": "2.3.3",

We use apollo as HOC.

fetchPolicy: 'no-cache', or notifyOnNetworkStatusChange: true, solved the problem.

@austincondiff notifyOnNetworkStatusChange: true worked for me as well. Given we have the same reproduction, I think it will work for you too.

Still seeing this issue with react-apollo 2.0.4. notifyOnNetworkStatusChange: true does not work in our case either.

The error on the console is the one that my back-end service sent back to graphql for one of the fields I am querying for (the other fields resolve fine, but this field gets set to null, as expected. However, I would also expect the client to set loading to false, so I can at least deal with the rest of the returned data. image

Anyone have a fix for this issue? I also an suffering from intermittent loading flag issues on the latest 2.0 release (it seems like these loading flag bugs have been around for nearly a year). As others have said it seems to trigger when a nested HOC has a property change and is interacting with the cached values (I don’t see the queries on the server side when this happens). I’ve tried the notifyOnNetworkStatusChange: true solution but it doesn’t seem to eliminate this completely.

I may end up downgrading to the 1.8.1 version and giving up on 2.0 until this is resolved.

The notifyOnNetworkStatusChange: true solution is not ideal. If we have a paginated list and try to load more data with fetchMore, the data.loading will be true and the whole list will be in loading state (Expect fetchMore not to trigger data.loading)

@jbaxleyiii the error is still there.

Basically, when there is a network error, the queryObservable is removed from graphql wrapper object (in react-apollo.browser.umd.js). Any refetch only update Apollo store but does not trigger a rerender of the components.

I found a workaround by adding a retry function to the data prop passed to the wrapped component in function dataForChild:

else if (error_1) {
		assign(data, (this.queryObservable.getLastResult() || {}).data, { retry: () => {
			this.unsubscribeFromQuery();
			this.queryObservable = null;
			this.previousData = {};
			this.updateQuery(this.props);
			if (!this.shouldSkip(this.props)) {
					this.subscribeToQuery();
			}
		} });
}

Then I can call this.props.data.retry() from the wrapped component to retry to fetch the data, and the component will receive new data prop without an error (if a valid response is received from the server).

This does not solve the polling issue (definitely stopped by an error).

Maybe this can help people facing other issues : #1622 #1601 https://github.com/apollographql/react-apollo/issues/642

I can also confirm that loading issue is gone in apollo-client 2.0 beta. But store still does not get reset as mentioned in https://github.com/apollographql/react-apollo/issues/807 and https://github.com/apollographql/react-apollo/issues/890.

Actually, looks like I spoke too soon, it’s possible I did something wrong and didn’t upgrade to Apollo 2.0 on my other project correctly

I went through the effort of forking the example in https://github.com/apollographql/react-apollo/issues/976 and it seems that it no longer repros in Apollo 2.0. See https://github.com/nbushak/apollo-reset-issue for anyone interested. Maybe this issue will be fixed on its own in 2.0? It sounds like the next step here is for folks to try to repro in 2.0? I’ll try to upgrade my main project to 2.0 as well to see if it stops reproing everywhere.

Can we drop the “reproduction-needed” label here? There are multiple ones listed at this point.

It stays true for me too when the result contains and empty array (same as @rlech) Using "react-apollo": "^1.2.0", and React Native.

I’m pretty sure now that it’s a caching issue. But I don’t know enough to provide a fix.

When the graphql HOC renders, it gets the data from QueryManager.getCurrentQueryResult, which tries to get the query result and consumes any errors. If there are any errors, it returns an empty data and partial: true. When you’re using the network caching, the partial is remapped as a valid result and loading is set to false, otherwise, loading is set to true, causing the infinite loading as there are no remaining events to change state on.

The reason getCurrentQueryResult is throwing an error in my case:

Error: Can't find field entityBySlug({"entitySlug":"Map","worldSlug":"game0"}) on object (ROOT_QUERY) {
  "current_user": null,
  "worldBySlug({\"slug\":\"game0\"})": {
    "type": "id",
    "id": "World:2",
    "generated": false
  }
}.
    at readStoreResolver (readFromStore.js:41)
    at executeField (graphql.js:74)
    at graphql.js:31
    at Array.forEach (<anonymous>)
    at executeSelectionSet (graphql.js:26)
    at graphql (graphql.js:20)
    at diffQueryAgainstStore (readFromStore.js:73)
    at readQueryFromStore (readFromStore.js:18)
    at QueryManager.getCurrentQueryResult (QueryManager.js:652)
    at ObservableQuery.currentResult (ObservableQuery.js:72)

It’s trying to find a result from the cache that doesn’t exist and falling through the try-catch. Which may be intentional, as it can retry until it is in the cache,

But, the graphql HOC doesn’t subscribe to the Redux store, it seems to subscribe to the Apollo Client (via QueryObservable), so once those queries do resolve and they get saved in the store (as everyone’s already mentioned), the HOC isn’t told so it just goes on, loading forever.

That’s what I’m thinking anyway. I can’t figure out how QueryObservable is being wired up to trigger re-renders when the data does come in. When the data is stored, the HOC explicitly decides not to rerender based on its unrelated props.

That’s as far as I’ll go here. Hope it helps someone with broader knowledge in how this is all wired up. Or maybe I’m completely wrong. 🤐

@tomitrescak I wonder if this is actually an interop issue between react-apollo and apollo-client. I think when reset store happens, the react tree isn’t rerendering correctly. Could you create a simple reproduction for me to take a look at?

Resolved: I’m using redux-persist. I added ‘apollo’ to the blacklist all is well.

Superb work, @dylanscott!

@nbushak ok, we’ll open it back up then!

@advance512 I had to update both apollo-client and react-apollo to versions 1.4.0 and 1.4.2 respectively.

Downgrading to 0.10.1 fixed for me. Updating Apollo Client 1.2.2 did not fix.

I can see in my dev tools that a request is being fired when my props are updated and is getting an appropriate response, but props.data.loading is never set to false and props.data never gets my queried data as one of its fields.

It’s a bit weird in my case, it was working okay in testing but when I generated a signed apk in react native and run that. For some queries loading never goes false. It’s just loading forever, but it works fine in testing environment