12

Is there a global loading flag available anywhere for react-apollo client? I have a “page wrapper” component that i’d like to apply ui effects to after all the child components have received their data.

I have set up apollo with redux so have ready access to the store (http://dev.apollodata.com/react/redux.html)

I could quite easily dispatch state changes from each component that receives data from apollo but I'd like this page wrapper component to not have any knowledge of its children nor their queries.

I have investigated using withApollo - http://dev.apollodata.com/react/higher-order-components.html#withApollo - but don't see an api for a global is loading.

elmpp
  • 550
  • 1
  • 7
  • 16
  • I suspect you could wrap withApollo with a HoC and add in your custom logic in there. – Clay May 16 '17 at 17:00
  • i'm at a loss whether `withApollo` offers any API for a global `loading` status? I thought perhaps via its `networkInterface` but not looking like it could? – elmpp May 16 '17 at 17:03
  • it does not out of the box. you could achieve it with a custom network interface but that seems like the wrong tool for the job. I suspect wrapping withApollo with something like withCustomApollo, you could check the loading state there. – Clay May 16 '17 at 17:11
  • But this isn't for any one specific component - i would like a separate component to be made aware of whether any graphql call at all is being made - unless i'm mistaken only the `graphql()` wrapped components themselves would receive the `data`/`loading` props – elmpp May 16 '17 at 17:14
  • oh, then you can definitely use a custom network interface. Wrap the network interface (either the batch or the default) then whenever it queries set that it is loading to a singleton variable. – Clay May 16 '17 at 17:32
  • you may also be to achieve it using a middleware on the network interface rather then doing what I described in the previous comment. you'll have to experiment figure out what's best for your use case. – Clay May 16 '17 at 17:34
  • Ah yes, this all sounds very plausible. I'm giving it a go with an `middleWare/afterWare` combination to keep a tally of unresponded calls - any idea of how to map a request to a response - my graphql protocol knowledge is a little sketchy here. Surely it's possible - apollo client matches them somehow – elmpp May 16 '17 at 18:23
  • This gist here suggests that request headers are persisted to response somehow so i'm good to go i think - https://github.com/apollographql/apollo-client/issues/657#issuecomment-258440056 Have accepted your answer - middlewares are the way to go here – elmpp May 16 '17 at 18:30

2 Answers2

5

I've just released a library that solves this for Apollo 2: react-apollo-network-status.

The gist is:

import React, {Fragment} from 'react';
import ReactDOM from 'react-dom';
import {ApolloClient} from 'apollo-client';
import {createNetworkStatusNotifier} from 'react-apollo-network-status';
import {createHttpLink} from 'apollo-link-http';

const {
  NetworkStatusNotifier,
  link: networkStatusNotifierLink
} = createNetworkStatusNotifier();

const client = new ApolloClient({
  link: networkStatusNotifierLink.concat(createHttpLink())
});

// Render the notifier along with the app. The
// `NetworkStatusNotifier` can be placed anywhere.
const element = (
  <Fragment>
    <NetworkStatusNotifier render={({loading, error}) => (
      <div>
        {loading && <p>Loading …</p>}
        {error && <p>Error: {JSON.stringify(error)}</p>}
      </div>
    )} />
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </Fragment>
);
const node = document.getElementById('root');
ReactDOM.render(element, node);
amann
  • 5,449
  • 4
  • 38
  • 46
3

You can achieve this in two ways:

One way is to use the middleware/afterware of Apollo's network interface.

The other way is to wrap Apollo's network interface to include your custom logic. Specifically you would wrap the query method.

Clay
  • 4,700
  • 3
  • 33
  • 49
  • can you explaing a little more? where can I read more about these method? like codesandbox code samples or documentations or github repo explaining this? – fafa.mnzm Jan 23 '22 at 20:54
  • My comment was from 5 years ago but with the latest version of Apollo, I believe you could create a `new ApolloLink()` that sets a global loading value to true/false depending on if a result has been received or not.. and then have a global function like `getApolloLoading` that updates the state in zustand or redux. But, if you need it to be aware of react state, you may want to initialize the ApolloClient and inside your `` component. – Clay Jan 23 '22 at 23:51
  • Do you have any sample code anywhere? I am using nuxtjs/apollo and I am using a local state loading and manually update it. I was wondering is there anything builtin in apollo link that would do this on the side. Or is there a way to use axios with apollo link? like is it a package it uses under the hood? – fafa.mnzm Jan 25 '22 at 18:12
  • I do not have any sample code. You might have more luck posting a StackOverflow question or reddit.com/r/reactjs. You can read the package.json of apollo's repos to see if it uses axios but it seems unlikely since it would be an unnecessary dependency. – Clay Jan 25 '22 at 18:20
  • thanks, I found '@nuxtjs/observable' gonna check it. then I just have to find how they make api calls in apollo client – fafa.mnzm Jan 25 '22 at 18:30