GraphQL + Apollo – Part 3: Building a Client

In case you are just tuning in, in this series, we have been taking a close look at GraphQL through the lens of the Apollo toolchain. Part 1 of the series explains some core concepts of GraphQL and introduces Apollo as a GraphQL solution. In Part 2, we took a closer look at building a GraphQL server with Apollo tools. Finally, in this post, we will take a look at the Apollo Client libraries and implement an example client to integrate with the example server from my previous post.

What is Apollo Client?

Apollo has several client implementations available. The core JavaScript library is a good place to start on the JavaScript side.

Apollo also has React and Angular integration packages for the web. In addition, it has an iOS implementation written in Swift! More non-JavaScript platforms (e.g. Java) are currently under development, which is very exciting.

Essentially, the Apollo Client toolchains enable you to integrate with any GraphQL server. They are not opinionated about how to construct your server schemas, and they are extremely flexible. The client libraries implement client-side query caching, query merging and batching, subscriptions, and optimistic UI. In this post, we will take a closer look at the React package in particular.

Configuring the Client

To get started using the library (after installing from npm), we need to set up an ApolloClient and ApolloProvider instance. ApolloClient is the core API for any Apollo Client integration. This is where you configure the network interface, the client side cache, and some global query behaviors.

ApolloProvider is a React component that wires the ApolloClient instance into your React component hierarchy. A pretty standard ApolloClient initialization is shown below. This creates an ApolloClient instance and specifies a network interface pointing to our GraphQL server’s endpoint (the same one we defined in Part 2). Then it shows how to wire the ApolloClient instance into the root React tree.


import { ApolloClient, createNetworkInterface } from 'react-apollo';
const client = new ApolloClient({
  networkInterface: createNetworkInterface({ uri: 'http://localhost:3000/api/graphql' }),
});

ReactDOM.render(
  <ApolloProvider client={client}>
    <MyApplication />
  </ApolloProvider>,
  document.getElementById('root')
)

Querying our Data

Now we are getting to the fun part! Building queries and mutations in Apollo is pretty simple. If you are using the core JavaScript implementation, there are query and mutate methods on the ApolloClient instance, which take a whole variety of parameters.

The most important argument that must be specified in any query or mutation call is the query/mutation string. An example query implementation for the personWithName query can be found below-this is the same query that we executed in GraphQL at the end of Part 2. The query and mutate methods return Promises, so this should be a familiar interface for integrating into your application. Additionally, the query syntax is same GraphQL standard that we are used to, so any query that you can input into the GraphiQL explorer can be used as a query in your Apollo Client.


client.query({
  query: gql`
    query($name: String!) {
      personWithName(name: $name) {
        gender,
        name,
        age
      }
    }
  `,
  variables: {
    name: 'George',
  }
});

As I mentioned earlier, the above example demonstrates the core query API for ApolloClient. However, with the React integration package, we have a much nicer API at our disposal. In react-apollo, queries and mutations are implemented with the graphql Higher Order Component. This HOC is a very useful utility for React integration because it:

  1. Takes care of synchronizing the fetching of data with rendering of the presentational component.
  2. Allows the creation of a declarative query that is bound directly to your props.
  3. Enables a strong decoupling of presentational components and Apollo.
  4. Provides hooks for customizing query inputs and child props (after data is received by Apollo).

Let’s take a look at how to build the same personWithName query with the graphql HOC. The example below continues the example from the ApolloClient configuration section above. We define the MyApplication component and a Greeter component, which just renders some details about the person which was retrieved by the query.



import { graphql } from 'react-apollo';
import gql from 'graphql-tag';

const Greeter = ({ person }) => <div>Hello {person.name} ({person.age} {person.gender})!</div>;

Greeter.propTypes = {
  // comes from MyApplication
  desiredName: React.PropTypes.string.isRequired,

  // comes from Apollo
  person: React.PropTypes.object,
};

Greeter.defaultProps = {
  person: {}
};

const PERSON_WITH_NAME_QUERY = gql`
  query($name: String!) {
    personWithName(name: $name) {
      gender,
      name,
      age
    }
  }
`;

const GreeterWithData = graphql(PERSON_WITH_NAME_QUERY, {
  options: ({ desiredName }) => ({ variables: { name: desiredName } }),
  props: ({ data: { personWithName } }) => ({
    person: personWithName
  }),
})(Greeter);

First, notice the PERSON_WITH_NAME_QUERY query, which should look identical to the query above. Next, we define the graphql HOC, passing in the query document and also the options and props functions. These two functions are hooks into the Apollo lifecycle that let you customize the query options and the props sent into the child component (i.e. Greeter, in this case). Each of these functions will be called by Apollo and pass in ownProps-which is just an object containing all props that were passed into it.

For the options function, we only care about the desiredName prop, which is passed in by MyApplication. Using this prop value, we set the name variable in the query. If this prop should ever change (for example if the MyApplication UI had a way for a user to enter in the desired name), then this options function would cause Apollo to refetch the data when that prop value changed. Pretty cool!

The props function receives the data prop from Apollo, which contains the query results along with a loading status (and a few more things as well). This props function lets us specify exactly how we want the child component to receive its props. So, in this case, all I want to do is change the personWithName object name to person, to allow for a better separation of my presentational component and GraphQL schema. This is obviously a very simple example, but I think it should be enough to see how powerful a mechanism like this is!

The Finished Product

Now, let’s see the result of our query from a browser! The image below shows the result of the query and the Greeter component. On the left side, you can see George is being greeted with some information about himself. On the right side, you can see the network request/response from the server that was triggered by the graphql HOC.

Conclusion

This series has been a lot of fun for me to write. There are a lot of awesome features that we didn’t even get a chance to talk about, but I hope this series gave you a good introduction to GraphQL and Apollo. My team has been really happy with Apollo so far, and I am excited to see where the community will go with these tools-I believe this is just the tip of the iceberg for GraphQL!