React-apollo: Child component stuck in loading state, but the data is already loaded.

Created on 25 Mar 2019  ·  42Comments  ·  Source: apollographql/react-apollo

Intended outcome:

There are two React components:
parent: Requests (stateful component)
child: graphql(List), having prop state

There's buttons in Requests, which are setting state.
In turn, List component's query variable is set by state prop, which is equals to state in Requests component.
So the data for List should be refetched every time I click button in Requests.

Actual outcome:

Data is refetched successfully, but sometimes (80% of times) List is stuck in loading state. If I click some other button again, loading is resolving, the data is new.

I did try install react-apollo 2.4.1 and it fixed the error.
Also, if I recreate component every time (key prop) it helps too.
BTW, [email protected] was having the same issue

How to reproduce the issue:

I did create code example using local state, but it works fine, so I suggest the problem reproduction is requiring real graphql endpoint.
Real GraphQL endpoint example is failing as expected:
https://codesandbox.io/s/039pyz78pn

Version

bug confirmed

Most helpful comment

A fix for this issue has been merged! Thanks to everyone who helped report and debug this issue

All 42 comments

also having this issue

@OurMajesty Any chance you could try building a reproduction using https://github.com/apollographql/react-apollo-error-template? It will simulate having a backend, so hopefully that will help.

@hwillson Yes, I did try it right away, but it worked fine. Furthermore, I have found additional places in my app, where it stucks too. For example, dynamic search, that's why I mentioned this issue in #2808.
I wish Launchpad still worked, it would help to reproduce.
Had a lot of work lately, but still planning to find a way. Maybe use some open GraphQL API.

If someone needs a workaround, right now I am using react-apollo 2.4.1 along with client 2.5.1 and other latest libraries and doesn't really found any compatibility issues, local state and client queries work fine too.

@hwillson I did finally reproduced it. The same Codepen link: https://codesandbox.io/s/039pyz78pn

First, click on "computer". Result: empty list.
Second, click on "noop". Result: empty list again.
And it stuck.

Having this exact same issue, seems to me that the issue is when variables change but the response remains the same.

I сonfirm this, updated the reproduction, added another button, which returns not empty data, but the same as "SDK" button, and it is stuck too, if you click them one after another.

Hello there,

I have the exact same issue, when the response is the same, no matter if the filters change, the loading state doesn't change and the component is stuck in a loading state.
If the list changes content there's no problem at all.

[email protected]
[email protected]

Also experiencing this in [email protected] and [email protected]. I have a select component updating a variable that's passed into my query. One of the selected values, when passed in as a variable to the query, produces an error and the other returns data. This is expected behavior in my case. But after switching back and forth twice, the query that was originally returning an error gets stuck in the loading phase.

Same issue.

"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
"apollo-link": "^1.2.11",
"apollo-link-error": "^1.1.10",
"apollo-link-http": "^1.5.14",
"apollo-link-state": "^0.4.2"

Got the same error with client.queryManager.refetchQueryByName()

I'm experiencing the same problem when the data returned from the previous query is the same as the latest query.

I am having the exact same Problem, loading State is not updating. Have Version 2.5.4.
Would be great if this Issue will be fixed in the next Version/s.

Any update on this, I'm also experiencing this issue.

Had this issue with "apollo-boost": "^0.3.1" , Query was always stuck on loading. This is with a pollInterval={1000}

My work around was

const shouldShowLoading = loading && !data.myData;
if (shouldShowLoading) {
  return <Loading />;
}

// use data.myData if it exists
doSomething(data.myData)

loading will be false until the data changes in the db. Otherwise, loading is always true with the same query params. However, data is still returned from the query, so I just used that instead.

"apollo-boost": "^0.3.1",
"graphql": "^14.2.1",
"react": "^16.8.6",
"react-apollo": "^2.5.4"
using 2 seconds polling

This is a clear bug and in my application it happens absolutely randomly. Drove me nuts. Have only one template query and a bunch of client queries/mutations. Wide use of react hooks/custom hooks.
Kudos to honestbonsai for brilliant work around!

I did some digging on this issue and the situation addressed here happens when falling into this condition. (https://github.com/apollographql/react-apollo/blob/master/src/Query.tsx#L335-L340)

This exists as mentioned in the comments (https://github.com/apollographql/react-apollo/blob/master/src/Query.tsx#L303-L309)

When the Query component receives new props, or when we explicitly
re-subscribe to a query using resubscribeToQuery, we start a new
subscription in this method. To avoid un-necessary re-renders when
receiving new props or re-subscribing, we track the full last
observable result so it can be compared against incoming new data.
We only trigger a re-render if the incoming result is different than
the stored lastResult.

I might be wrong but while above is a valid approach, maybe there is an assumption that this.queryObservable's next is going to be fired at least twice(when loading: true & loading: false)? But as I was investigating, loading is true only when this.querySubscription is newly assigned, i.e. when Query component is mounted.
In other cases such as changing query variables, next is fired only when the new data arrived and loading is false, which means even when query variables changed if the query result is shallowly equal by chance(such as empty array), Query component doesn't call forceUpdate and loading remains true in the child components.

In @OurMajesty 's reproduction link, if you press "computer" and "noop" back and forth, loading stays true since both cases the query result is an empty array.

https://codesandbox.io/s/039pyz78pn

Also experiencing this issue. On "apollo-client": "^2.6.0","react-apollo": "^2.5.6".
We only trigger a re-render if the incoming result is different than the stored lastResult. Is it possible to make this a option we can override, i.e force re-renders or atleast it should not be stuck in loading? Or integrate the boolean workaround by @honestbonsai into loading

I skip/comment the loading condition and it works.
Also I try the workaround by @OurMajesty using react-apollo 2.4.1 and it works too.

I have no skip in the reproduction. There's probably another different error, when skip is helpful: #2808

@hwillson some attention on this issue?

Also having this issue.

Hi everyone! Thanks for catching this bug, and thank you @OurMajesty for providing a great reproduction. I will continue to investigate the source of this bug, but in the meantime I may have found another workaround.

In my tests on the reproduction, it appears that this issue only happens when the query's fetchPolicy is "network-only". Changing the fetchPolicy to something else, such as "no-cache" results in proper loading of the query (more info on fetchPolicy: https://www.apollographql.com/docs/react/api/react-apollo/#optionsfetchpolicy). I'm curious to see if this change works for the rest of you who are also reporting the issue. Please let me know!

Commenting out fetchPolicy: "network-only" is helping in the reproduction - loading is never stuck.
fetchPolicy: "cache-only" helps too, and saves "network-only" behavior (request made every time)
But I have two issues with such workaround:

  • there's cases, when I still need to get some data from the cache, which contains latest fetched data (example: isInCart resolver for product, which uses some cart data from the cache, but the cart itself is network-only)
  • when using "cache-only" fetchPolicy first render is neither loading or error, but there's no data, second render is having the data:
    изображение

no-cache seems to be helping. Will have to test more and confirm

A fix for this issue has been merged! Thanks to everyone who helped report and debug this issue

This thread _appeared_ to be the same issue I'm having except I have now updated to apollo-client 2.6.3 and still have a loading indicator that occasionally stays true despite the query returning from my API quickly and successfully.

I believe I have found the pattern that is the difference. The issue appears to be caused by having more than one <Query> polling at the same time. I have a parent component using <Query> to poll every 10 seconds for fresh data.

    <Query query={query} variables={{ id: 1234 }}>
      {({ loading, error, data, startPolling }) => {
        if (error) {
          return <div>Error!</div>;
        }

        if (!loading) {
          startPolling(5000);
        }      

There is a child component with a 2nd <Query> also doing 10s polling for a different set of data.

When both requests kick off at the same time (or very close), the loading problem occurs.

To be clear, the API requests are coming back fast and successful. They are, in fact, not loading despite the fact loading=true is returned by <Query>.

If I turn off polling on my parent component (<Query> #1), the loading indicator issue goes away in the child component (<Query> #2).

Hi @TroyWolf, thanks for reporting that issue! I've moved it to a new thread, #3226, because I think it's slightly different than the original issue here.

A fix for this issue has been merged! Thanks to everyone who helped report and debug this issue

What's the fix? I'm using "apollo-client": "^2.6.2" And noticed this in my HOC when I refresh the page.
The HOC checks if user is logged in but uses cache-first for speed.

@developdeez The fix was to the internals of how react-apollo keep track of query results, which was merged in #3126. If you use the latest version of react-apollo 2 or 3, this exact problem shouldn't happen anymore. Note that this issue was pretty much exclusively about the network-only fetch policy, so if you're seeing an issue with cache-first I recommend that you create a separate issue. Thanks.

+1 I have the same problem using react apollo 3

This problem is definitely not fixed.

If anyone here can provide an updated repro that uses React Apollo 3.1.0, we'll take a look. Thanks!

I'm on 3.1.0 and still loading forever unless using no-cache fetch policy. We are still using Query HOCs, not even hooks yet. I could try to get a minimal repro — is there a repo I should fork to try to get a repro?

I did update my old repro to latest react-apollo and everything works fine:
https://codesandbox.io/s/039pyz78pn

@OurMajesty yeah it seems to work fine in your updated sandbox. Congrats!

I'm trying to reduce my production code to a minimal example. Are there any good debugging tools for debugging or logging, such as dumping the apollo cache or logging when a query is staying loading too long?

I would suggest Apollo Dev Tools and also apollo-link-logger

In React Native app:

"react-apollo": "^3.1.0-beta.0",
"@apollo/react-hooks": "^3.1.0-beta.0",

same problem. :-(

Anyone know if this is perhaps fixed in 3.1.1? NPM says was released 2 days ago

Anyone know if this is perhaps fixed in 3.1.1? NPM says was released 2 days ago

I just updated from 3.0.1 to 3.1.1 after seeing your comment and it fixed it for me. Mine was getting stuck loading after getting a 500 from the server using the useQuery hook.

Using 3.1.3 but still having the same issue using the Query element (when the same data is returned), setting the fetchPolicy prop to "cache-only" seems to fix it for now.

Also experiencing this and waiting for a fix.

@hwillson @jbaxleyiii @helfer @jasonpaulos Can you please reopen this issue? Someone opened a new issue: #3774
Would appreciate it if you can take a look at it since this bug has been present since a rather long time.

@ajhool @nmklotas If you can create a minimal repo that reproduces the issue, it'll really help the maintainers in fixing this

Related: #3488 #3361 #3425

Was this page helpful?
0 / 5 - 0 ratings