React-apollo: loading is always True in Query render prop

Created on 17 Apr 2018  路  39Comments  路  Source: apollographql/react-apollo

I am using query render prop, which been wrapped by a redux render prop, which provides a new query for a new fetch. But when the new fetch been triggered, the loading is always true in the Query render prop.

expected: the loading state should be false once data has been returned
actual: the loading state is always true

It seems that the loading is always true if data is the same? but it's not consistant

apollo-client: 2.2.8
react-apollo: 2.1.3

Code:

<WithRedux id={id}>
          {
            ({ d }) => {
              return (
                <Query query={getQuery(d)}>
                  {({ loading, error, data, refetch, networkStatus }) => {
                    console.log('.....networkStatus', networkStatus);
                    console.log('.....loading', loading);
                    console.log('.....data', data);
                    if (error) return <CompPlaceholder cnt={1} template={0} />;
                    if (loading) return <CompPlaceholder cnt={1} template={1} />;
                    if (data && Object.keys(data).length > 0) {
                      if (data.flightInfo && data.flightInfo.length > 0) {
                        return (
                          <DetailFlightInfoCard id={id} data={data.flightInfo} />
                        );
                      }
                      return null;
                    }
                    return null;
                  }}
                </Query>
              );
            }
          }
        </WithRedux>

apollo client with batchLink and cache

new ApolloClient({
    link: batchLink,
    cache: new InMemoryCache(),
    connectToDevTools: true,
  });
reproduction-needed

Most helpful comment

same issue

react-apollo @ 2.5.2
apollo-client @ 2.5.1

notifyOnNetworkStatusChange did not work

All 39 comments

I can confirm.

Facing the same issue using the same versions

Facing same problem.
When response data exceeded certain size, it didn't catch the response with data.

I鈥檓 seeing loading === true And networkStatus === 1 when using skip={true} which I certainly didn鈥檛 expect. No request is actually being sent (which is correct) but the props passed to the render function would suggest one is.

same problems please fix it.

Experiencing the same thing here on 2.3.2.

image

Above you can see two consecutive queries, both returning an empty array as data. First one works fine, switching loading flag to true and then back to false. Second one, freezes at true and never flips back.

image

Network tab shows both /graphql requests completed successfully and returning the same payload.

After digging around Query.tsx code, I found out that the main issue is that its render() method never gets called if the same data is fetched twice from the network, so children render function is also never invoked.

This seems to be relying in this.queryObservable to trigger a next callback call, which never happens under these conditions - so issue might actually lie in the client.

Ok, finally discovered the underlying cause. It's this line on apollo-client preventing consecutive, identical results from being propagated to the observer. The actual fetched data is compared here.

          if (observer.next) {
            if (
              previouslyHadError ||
              !observableQuery ||

               // This is causing the issue 馃憞 
              observableQuery.isDifferentFromLastResult(resultFromStore) 
            ) {
              try {
                observer.next(resultFromStore);
              } catch (e) {
                // Throw error outside this control flow to avoid breaking Apollo's state
                setTimeout(() => {
                  throw e;
                }, 0);
              }
            }
          }

Replacing observableQuery.isDifferentFromLastResult(resultFromStore) with just true makes the problem go away and <Query> re-renders properly.

Follow up: it turns out my particular issue was caused by apollo-cache-hermes, which I have been using as a substitution for apollo-inmemory-cache. Switching back to latest apollo-inmemory-cache resolved the problem for me.

You can find a repro case here:

Edit apollo-client-error-template

I'm not using the <Query /> component, but I'm also having this problem with the graphql function if I use skip() and have two queries that result in the same data. Remove skip(), or remove one of the components that tries to fetch, and it works fine.

I seem to be encountering this same issue even without any cache in place. Using a <Query /> with the prop fetchPolicy="network-only" passed, if I make a query that is functionally the same as the previous query (for instance, the fields are the same but in a different order) and the response is the same the loading argument will come back true after the request has successfully completed.

apollo-client: "2.4.2"
react-apollo: "2.1.11"

For what it's worth, this comment from #1186 recommends passing the notifyOnNetworkStatusChange props, which worked for me.

same issue

react-apollo @ 2.5.2
apollo-client @ 2.5.1

notifyOnNetworkStatusChange did not work

@nfantone you say that changing the line observableQuery.isDifferentFromLastResult(resultFromStore) to true solves the problem. How did you end up determining that apollo-cache-hemes was the actual source of your issues?

If we know the solution to the problem, could we make a pull request to fix it?

The notifyOnNetworkStatusChange: true workaround worked well for us using apollo-client 2.4.8 and earlier. But this workaround no longer works with apollo-client 2.5.1

Using apollo-client 2.5.1, the original issue of the second identical data not causing loading to be set to false returns.

@mac-s-g in my experiene the work around only works for 2.4.x and older

@baleeds It's been some time now and I don't really remember details, but yours is a good question. Both approaches worked: replacing apollo-cache-hermes and forfeiting isDifferentFromLastResult validation. So my guess is that resultFromStore ends up being different in each cache implementation, somehow.

https://github.com/apollographql/react-apollo/pull/2840 should help address the issues mentioned here, starting from https://github.com/apollographql/react-apollo/issues/1931#issuecomment-471242011. We're hoping to have a new react-apollo release published either later today / tomorrow.

@city41 rolling back to 2.4.1 fixed the issue for now.
thank you!

We just ran into this.. Any updates on a fix?

We just ran into this.. Any updates on a fix?

Could this be the fix for you: notifyOnNetworkStatusChange: true ? I works for me.

@ciulic nope - that didn't fix. ended up having to expose the requestTime on the api so that i could make the responses distinct, which.. is very hacky

Setting notifyOnNetworkStatusChange to true worked for me, but I personally wouldn't consider this a solution, just a bandaid

Confirm setting notifyOnNetworkStatusChange to true worked for me.

"apollo-client": "2.5.1"
"react-apollo": "2.5.5"

Hi @hwillson I saw that (#2840) landed. From your above comment, it seems that maybe this was intended to fix the "infinite loading" when data from the network matched data in the cache. I am currently on react-apollo: 2.5.5 and apollo-client: 2.5.1 and still experiencing this behavior. I am able to ensure the re-render by providing notifyOnNetworkStatusChange = true to the <Query> component.

I am curious what you think about setting that property to true by default when fetchPolicy="network-only". It would seem to me that it would be a rare case to request network-only but also not want to be notified about the result of that network call (even if it is the same data in cache).

This is a pretty obscure bug to track down if not for this long standing issue being open, so I wonder if we can have some more sensible defaults.

I'm still facing this problem. But this only occurs when performing 2 queries on the same component using compose. This is very annoying.

"apollo-client": "^2.6.0"
"react-apollo": "^2.5.6"

I had the same issue with giving skip directive if the variable $noSessionExists is true. I accidentally was providing $sessionExists variable instead causing the query to be in the loading state forever.

Anyone facing the issue might also want to check if the variable they are passing is okay. I wasted a couple of good minutes trying to think it was a bug. Turns it was me all along. Damn !

export const GET_COURSE_GLOSSARY = gql`
    query getCourseGlossary(
        $sessionId: String!
        $glossarySkip: Int!
        $limit: Int!
        $uniqueChapterId: String!
        $uniqueTopicId: String!
        $noSessionExists: Boolean!
    ) {
        getCourseGlossary(
            sessionId: $sessionId
            skip: $glossarySkip
            limit: $limit
            uniqueChapterId: $uniqueChapterId
            uniqueTopicId: $uniqueTopicId
        ) @skip(if: $noSessionExists) {
            total
            glossary {
                id
                term
                definition
                definitionHtml
                summary
                notes
            }
        }
    }
`;

I can confirm the issue is hapenning for us too.
"apollo-client": "2.5.1"
"react-apollo": "2.5.5"
and notifyOnNetworkStatusChange works

Hi everyone! It seems like some of you are having the same issue as #2899, which was fixed in the most recent versions of react-apollo 2 and 3. Please let me know if your issue has been fixed by this update, and if not, it would be very helpful to us if you could provide an up-to-date reproduction of the issue. Thanks!

Updating to "react-apollo": "^2.5.8" and "apollo-client": "^2.6.3" fixed the issue for me. Thanks for your help.

Confirm setting notifyOnNetworkStatusChange to true worked for me.

"apollo-client": "2.5.1"
"react-apollo": "2.5.5"

Work for me on
"apollo-client": "^2.4.2"
"react-apollo": "^2.1.11"

Thanks @escapiststupor

We're having the same problem. Multiple components on our pages are not updating loading to true, and it's really annoying.

We're using the latest (2.6.3) version, and our app is built with @apollo/react-hooks we now have to revert all our components to non-hooks and use the old version of apollo-client as a workaround to fix it.

Stuff randomly breaks...

Anybody out there that has another solution?

Big problem here...

"apollo-client": "^2.6.3",
"react-apollo": "^2.5.8"

Still with this issue

 const { loading, error, data } = useQuery(GET_EVENTS, {
    client: new ApolloClient({
      link: new HttpLink({ uri: `${env.graph}/events` }),
      cache: new InMemoryCache({}),
      name: "Events"
    }),
    notifyOnNetworkStatusChange: true,
    fetchPolicy: "network-only"
  });
  if (loading) return <Aux>"Loading..."</Aux>;
  if (error) return <Aux>Error! {error.message}</Aux>;

Keeps fetching data and loading is always true

The problem outlined in https://github.com/apollographql/react-apollo/issues/1931#issuecomment-517656612 was fixed just before the release of React Apollo 3, in https://github.com/apollographql/react-apollo/pull/3313. I don't think the problems outlined in this issue thread are still an issue in React Apollo 3, but if anyone notices otherwise, and can supply a small runnable reproduction, we'll definitely take a look.

@Dalejan You say you're using useQuery, but also that you're using react-apollo@2 which doesn't have useQuery. instead of a code snippet, would you be able to supply a reproduction?

I have updated to "react-apollo": "^3.0.0" but still stuck in loading state when using useQuery. Note: this is not happening whe using 'Query' Component, only with hooks.
Screenshot from 2019-08-13 11-58-42
In the console, data is empty and loading is always true. But the network response return the expected results in data.

@Dalejan any chance you can put together a small runnable reproduction of this?

@Dalejan i think you mean loading is always true when loading the same query again even when the data is in cache ? (when using cache-and-network). This is normal

Same issue as @Dalejan "@apollo/react-hooks": "^3.0.1",

React Apollo has been refactored to use React Hooks behind the scenes for everything, which means a lot has changed since this issue was opened (and a lot of outstanding issues have been resolved). We'll close this issue off, but please let us know if you're still encountering this problem using React Apollo >= 3.1.0. Thanks!

Same issue, I had to roolback to version 2.5.8 (from 3.1.2). This fix it for me!

Having the same issue with @apollo/react-hooks version 3.1.3.

cc @RRicardotj

Was this page helpful?
0 / 5 - 0 ratings

Related issues

notadamking picture notadamking  路  3Comments

dmitryyankowski picture dmitryyankowski  路  3Comments

tomitrescak picture tomitrescak  路  3Comments

thisbejim picture thisbejim  路  3Comments

jakelacey2012 picture jakelacey2012  路  3Comments