GraphQL and the amazing Apollo Client

Gerard Sans
Google Developer Experts
9 min readAug 14, 2016

Explore an Application built using React and Angular

Geometric Shapes / 160327 by Sasj Ecoline

Update 7-Nov: all code updated to Apollo Client 0.5!

In this article, we will use an early access to Graph.cool a GraphQL Backend-as-a-Service and the Apollo Client to show how to implement a Todo List using GraphQL in React and Angular.

GraphQL was developed internally at Facebook in 2012. Its main goal was to allow Native Mobile teams to quickly build new products and collaborate within the large Facebook ecosystem without disrupting existing Data Services. In July 2015, Facebook decided to open source it. They published an specification, and provided a reference implementation, using JavaScript (graphql-js), to get feedback from the community and allow other implementations to emerge.

Apollo Client is a framework-agnostic GraphQL client that helps you fetch data and keep your client state in sync with the server.

Introduction to GraphQL

GraphQL can be used either to refer to the GraphQL Specification, an implementation of a GraphQL Server or the Data Query Language.

GraphQL Server (Source)

There are many GraphQL Server implementations using: Python (graphene), Scala (sangria), Go, PHP, Java and more!

Why use GraphQL?

These are some reasons given by people using it

  • Super fast: single round-trip, only fetch what you need, designed for low latency.
  • De-coupled from storage: view-centric, client-specified queries, integrates with any current infrastructure.
  • Declarative: defines what we want, not how we get it; always backwards compatible.
  • Validated and Structured: strongly typed via a hierarchical schema allowing query validation, nested queries and predictable output.
  • Facilitates collaboration: discoverable via introspection, self-documented via in-browser IDE GraphiQL.

GraphQL is mature but still an evolving technology so best practices are still emerging.

Experimental features

GraphQL is very popular in the React community. It is usually composed by a GraphQL Server using Express.js (express-graphql) and a GraphQL Client, using either Relay, Apollo Client or lokka, usually in combination with Redux.

REST vs GraphQL

GraphQL offers few advantages over REST. Probably the most important are:

  • Single Client endpoint: clear separation between the Client and any underlaying Data Services.
  • Single round-trip: multiple and nested structures are fetched and merged for us and returned at once.
  • Simple and composable API: GraphQL Query Language avoids REST endpoints explosion.
  • Self-documented: via in-browser IDE GraphiQL.

See an overview diagram below.

How do I GraphQL? by Jonas Helfer

GraphQL Schema

Let’s explore a basic schema to familiarise with the semantics and query syntax.

For the schema above we defined two entry points (lines 15–16) query and mutation (covered later on). These will allow us to read and modify our data. This schema defines two types: Root and User. All the remaining types are built-in scalar types: Int, Float, String, Boolean, ID.

We can use the exclamation mark to indicate non-nullable types (line 4) or arguments (line 11). Default values for arguments can be defined using equals (line 11).

Queries and Output

The way you query the previous schema is following the field definitions on the left and navigating to the types on the right. See some examples below (compressed format)

# Basic queries
query { me { id name } } # anonymous query
^1 ^2 # 1: Root Type; 2: User Type
query MyQuery { me { id name } } # named query: MyQuery
{ me { id name } } # query keyword is optional
# Using arguments
# forUser is mandatory, limit default value is 5 (see schema)
query { friends(forUser:'cir9') { id name } }
query { friends(forUser:'cir9', limit:3) { id name } }
# Nested queries
# Include child Types by adding its name and fields
query { me { id name friends { id name } } }

Note how we can omit the query keyword although it’s not a recommend practice

Let’s see an example of a query and its output. For the query (left) we will get the output (right) below

# query                      # JSON output
{
{ "data": {
me { "me": {
name "name": "GraphQL ninja"
} }
} }
}

Queries return a JSON object following the exact query structure under data. If you ever need to change the output keys you can use aliases.

# query                      # JSON output
{
{ "data": {
user: me { "user": {
fullName: name "fullName": "GraphQL ninja"
} }
} }
}

GraphQL output is predictable and aligned to query structure by strictly following the schema

Fields composition (fragments)

We can also reuse and group fields by using fragments. A nested query we presented before could be changed to

query { 
me {
...userInfo
friends {
...userInfo
}
}
}
fragment userInfo on User {
id
name
}

Fragments can also be used by other fragments

Error handling

If for any reason there is an error for the previous query we would get an output like this

To learn more, we recommend you: Learn GraphQL, an interactive course made by Kadira.

GraphiQL

Twitter GraphQL Playground

GraphiQL, pronounced /ˈɡrafək(ə)l/, is the in-browser IDE for GraphQL. By using this IDE, we can run queries and mutations; see the output; debug; and more importantly browse the GraphQL Schema that serves as documentation. Play with this more advanced schema and sample queries using Twitter GraphQL API thanks to GraphQL Hub.

Todo List Application

We are going to create a basic Todo List Application where we can add new todos, mark them as complete and filter them as the demo below.

This is a simplified version in HTML.

Backend

We used Graph.cool to quickly create the schema below (simplified).

Request an early access to Graph.cool like I did here ❤️

React version

In order to setup the Apollo Client (apollo-client) we need to first inform the GraphQL Server endpoint.

dataIdFromObject property allows us to inform Apollo Client to use the record id for caching purposes

Bootstrap Setup

Let’s see how we need to setup our bootstrap to get the Apollo Client working with React. We will use react-apollo to do it.

Apollo Client uses his own reducer that we need to add to our Redux setup using combineReducers (line 9). Besides that, we also need to add the apollo middleware (line 14) to include Redux support for queries and mutations. Finally, we will add the ApolloProvider element to inject the client, the Apollo Client instance pointing to our backend, and the store to React’s view hierarchy (lines 19–21). After this setup, our store will have the following structure.

{
filter: 'SHOW_ALL',
apollo: ... // queries, mutations, data, optimistic
}

The filter reducer is transient and local to the client

React Integration

The code below (simplified) shows how we can integrate queries and mutations in our TodoApp component.

We use a series of wrapping functions returned by graphql to bind our queries and mutations to props in our TodoApp Component. These props will be created as seen below so we can pass them down to child components:

this.props.todos 
this.props.addTodo
this.props.toggleTodo

For greater control we use the props key to exactly define what we want to be binded on each case, being data results (lines 9–11) or mutation calls (lines 15–17, 21–23).

Retrieving the list of todos

Let’s take a look at the query that fetches the list of todos, todosQuery object (line 8).

This is a named query todos fetching all todos, defined in the schema as allTodoes and using the fields: id, complete and text. forceFetch flag indicates that we want to fetch the backend even if we have a cached version of the data. By default, Apollo Client fetches all queries during bootstrap.

gql preceding the query, is a template literal tag that parses GraphQL query language

Apollo Client binds the results via props so we can pass them into the TodoList component like below

<TodoList todos={this.props.todos} />

To render the list within the TodoList we can use the todos prop

TodoList.js

These examples should be enough to get you started. You can find examples of how to use updateQueries in mutations in the final code at the end.

Check latest documentation on react-apollo in the official docs.

Angular version

Same as we did in React, in order to setup the Apollo Client (apollo-client) we need to inform the GraphQL Server endpoint.

For Angular we will use angular2-apollo to integrate with Apollo Client.

Retrieving the list of todos

Let’s see how we can display the list of todos. First we need to retrieve any existing todos from the GraphQL Server. We will do this on our root component App.

We inject the apollo instance using Dependency Injection on our constructor (line 11). We will use query (line 13 ) returning a Promise to retrieve the list of todos. Once we get the results, we will dispatch the INTIAL_LOAD action using a helper. We can catch any errors by using the Promise catch error handler (lines 27–29).

Adding a new todo

In order to add a new todo we are going to use a mutation. Mutations allow us to change our data and also fetch results in one operation.

The addTodo mutation (lines 18–21) takes a string text, as a mandatory input (exclamation mark) and calls createTodo with two arguments: text and complete, with the value false. This will create a new todo with corresponding values and return its resulting id. In Apollo Client we can pass arguments to mutations using the variables object (line 23).

Once we get the response back we use the new created id to dispatch a ADD_TODO action using a helper, updating the UI (lines 27–31).

Check latest documentation on angular2-apollo in the official docs.

Wrap up

We briefly introduced GraphQL and showed how you can use Apollo Client to create a Todo List application using React and Angular. Hope you enjoyed and got excited about GraphQL and Apollo Client! Thanks for reading. Have any questions? Ping me on Twitter @gerardsans.

Integrations for React (react-apollo) and Angular (angular2-apollo) are fast changing so stay tuned for improvements and new features.

Resources

--

--

Gerard Sans
Google Developer Experts

Helping Devs to succeed #AI #web3 / ex @AWSCloud / Just be AWSome / MC Speaker Trainer Community Leader @web3_london / @ReactEurope @ReactiveConf @ngcruise