Beau
Beau

Reputation: 11358

How can I use Apollo/GraphQL to incrementally/progressively query a datasource?

I have a query like this in my React/Apollo application:

const APPLICATIONS_QUERY = gql`
  {
    applications {
      id
      applicationType {
        name
      }
      customer {
        id
        isActive
        name
        shortName
        displayTimezone
      }
      deployments {
        id
        created
        user {
          id
          username
        }
      }
      baseUrl
      customerIdentifier
      hostInformation
      kibanaUrl
      sentryIssues
      sentryShortName
      serviceClass
      updown
      updownToken
    }
  }
`;

The majority of the items in the query are in a database and so the query is quick. But a couple of the items, like sentryIssues and updown rely on external API calls, so they make the duration of the query very long.

I'd like to split the query into the database portion and the external API portion so I can show the applications table immediately and add loading spinners for the two columns that hit an external API... But I can't find a good example of incremental/progressive querying or merging the results of two queries with Apollo.

Upvotes: 2

Views: 952

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84657

This is a good example of where the @defer directive would be helpful. You can indicate which fields you want to defer for a given query like this:

const APPLICATIONS_QUERY = gql`
  {
    applications {
      id
      applicationType {
        name
      }
      customer @defer {
        id
        isActive
        name
        shortName
        displayTimezone
      }
    }
  }
`

In this case, the client will make one request but receive 2 responses -- the initial response with all the requested fields sans customer and a second "patch" response with just the customer field that's fired once that resolver is finished. The client does the heavy lifting and pieces these two responses together for you -- there's no additional code necessary.

Please be aware that only nullable fields can be deferred, since the initial value sent with the first response will always be null. As a bonus, react-apollo exposes a loadingState property that you can use to check the loading state for your deferred fields:

<Query query={APPLICATIONS_QUERY}>
  {({ loading, error, data, loadingState }) => {
    const customerComponent = loadingState.applications.customer
      ? <CustomerInfo customer={data.applications.customer} />
      : <LoadingIndicator />
    // ...
  }}
</Query>

The only downside is this is an experimental feature, so at the moment you have to install the alpha preview version of both apollo-server and the client libraries to use it.

See the docs for full details.

Upvotes: 2

Related Questions