In the previous article, I talked about different technologies sprouting around GraphQL. Today I’m going to specifically focus on the works of Apollo GraphQL. This is one developer community that seems to be on the fore-front on client-side implementations and giving Relay a run for their technology. This a good thing since the implementations by Apollo GraphQL are very simplified and easy to get started with. But with new technologies, come new challenges.

Queries

React Apollo 2.1 has been released and there are some interesting things one will need to understand. The previous versions took a more Redux-like approach to connect the components to the Apollo Client. The good thing is it’s 100% backward compatible. Here’s an extract from one of my projects using react-apollo 2.0.4. This code fetches a list of books from a GraphQL server. Note how we connect the component to the client.

... import gql from "graphql-tag";

import { graphql } from "react-apollo"; ... export const getBooksQuery = gql`

query getAllBooks {

books: fetchAllBooks {

id

title

description

}

}`; const BooksComponent = (props) => {

let { error, loading, books } = props.data;

if (error) return <div> An Error Occurred</div>;

else if (loading)

return ( <div style={styles.loaderSection}>

<CircularProgress />

</div>

);

else return ( /* Render the list of books here */ );

}; const BooksComponentWithData = graphql(getBooksQuery)(BooksComponent); export default BooksComponentWithData;

With the above connection using graphql , we get to access three important props inside our component which we can use to show appropriate messages to the user.

let { error, loading, books } = props.data;

we could also use withApollo in place of graphql to connect the component.

I have skipped the minor details and imports, here’s the complete component on Github.

Now here’s an example from the Apollo GraphQL migration docs and the difference is very obvious and more “React”.

import { Query } from "react-apollo";

import gql from "graphql-tag";



const ExchangeRates = () => (

<Query

query={gql`

{

rates(currency: "USD") {

currency

rate

}

}

`}

>

{({ loading, error, data }) => {

if (loading) return <p>Loading...</p>;

if (error) return <p>Error :(</p>;



return data.rates.map(({ currency, rate }) => (

<div key={currency}>

<p>{`${currency}: ${rate}`}</p>

</div>

));

}}

</Query>

);

We still have access to loading, data and error as before. Note the Query component from react-apollo . Another advantage here is Apollo Client automatically caches the data so you won’t seed a loading indicator if you run the query twice.

The above implementation will automatically fire the query when the component loads. What if you want the query to be triggered by the user manually? Here’s where we get ApolloConsumer. Here’s another snippet I have borrowed from the Apollo docs. In this situation, we have direct access to the client in the render prop function.

import React, { Component } from 'react';

import { ApolloConsumer } from 'react-apollo';



class DelayedQuery extends Component {

state = { dog: null };



onDogFetched = dog => this.setState(() => ({ dog }));



render() {

return (

<ApolloConsumer>

{client => (

<div>

{this.state.dog && <img src={this.state.dog.displayImage} />}

<button

onClick={async () => {

const { data } = await client.query({

query: GET_DOG_PHOTO,

variables: { breed: "bulldog" }

});

this.onDogFetched(data.dog);

}}

>

Click me!

</button>

</div>

)}

</ApolloConsumer>

);

}

}

Mutations

Here’s a sample component that creates a new book record through a mutation.

import gql from "graphql-tag";

import { graphql } from "react-apollo";

import { getBooksQuery } from "./BooksComponent"; /* Re-use the

query from the Query section */ /* Create the mutation */ export let createBookMutation = gql`

mutation createBook($title: String!, $description: String!) {

createBook(title: $title, description: $description) {

id

title

description

}

}`; class NewBook extends Component {

...

createBook () {

...

/* We can access the mutation method through the props*/

this.props.createNewBook(this.state.title, this.state.description).then(data=> {/* Logic for result */});

...

} render() {/* Render Logic(Form to create book) */}

} const NewBookComponentWithData = graphql(createBookMutation, { props: ({ mutate }) => ({

createNewBook: (title, description) => mutate({

variables: { title, description },

update: (store, { data: { createBook } }) => {

/*Read the data from our cache for this query. */

try {

const data = store.readQuery({ query: getBooksQuery });

/* Add our book from the mutation to the end */

data.books.push(createBook);

/* Write our data back to the cache. */

store.writeQuery({ query: getBooksQuery, data });

} catch(err){

console.log("Cache Error:", err);

}

},

})

})

})(NewBook); export default NewBookComponentWithData;

Here’s the complete component on Github.

Even after removing the optimistic UI section, the connection still looks like too much. This is an equivalent of mapDispatchToProps and doesn’t look any simple compared to its query counterpart.

Here’s an extract from the Apollo GraphQL docs of a similar implementation in react-apollo 2.1.

import gql from "graphql-tag";

import { Mutation } from "react-apollo";



const ADD_TODO = gql`

mutation addTodo($type: String!) {

addTodo(type: $type) {

id

type

}

}

`;



const AddTodo = () => {

let input;



return (

<Mutation mutation={ADD_TODO}>

{(addTodo, { data }) => (

<div>

<form

onSubmit={e => {

e.preventDefault();

addTodo({ variables: { type: input.value } });

input.value = "";

}}

>

<input

ref={node => {

input = node;

}}

/>

<button type="submit">Add Todo</button>

</form>

</div>

)}

</Mutation>

);

};

The above implementation looks way cleaner and straight forward.

In the above snippet, we pass a GraphQL mutation string wrapped with the gql function to this.props.mutation and provide a function to this.props.children that tells React what to render. The Mutation component is an example of a React component that uses the render prop pattern. React will call the render prop function you provide with a mutate function and an object with your mutation result containing loading, error, called, and data properties. First, create your GraphQL mutation, wrap it in gql , and pass it to the mutation prop on the Mutation component. The Mutation component also requires a function as a child (also called the render prop function). The first argument of the render prop function is the mutate function, which is how you tell Apollo Client that you’d like to trigger a mutation. The mutate function optionally takes variables , optimisticResponse , refetchQueries , and update ; however, you can also pass in those values as props to the Mutation component. In the example, notice the use of the mutate function (called addTodo ) to submit the form with our variables. The second argument to the render prop function is an object with your mutation result on the data property, as well as booleans for loading and if the mutate function was called , in addition to error . If you’d like to ignore the result of the mutation, pass ignoreResults as a prop to the mutation component.

A sample code to update the cache might look like the following:

...

<Mutation

mutation={ADD_TODO}

update={(cache, { data: { addTodo } }) => {

const { todos } = cache.readQuery({ query: GET_TODOS });

cache.writeQuery({

query: GET_TODOS,

data: { todos: todos.concat([addTodo]) }

});

}}

>

...

The implementation is very similar to the previous versions only cleaner.

Apollo-boost

Previously, we needed to install several(many) packages to set up Apollo client. Apollo boost brings all these packages and allows to install only one package instead.

Apollo Boost includes some packages that we think are essential to developing with Apollo Client. Here’s what’s in the box:

apollo-client : Where all the magic happens

: Where all the magic happens apollo-cache-inmemory : Our recommended cache

: Our recommended cache apollo-link-http : An Apollo Link for remote data fetching

: An Apollo Link for remote data fetching apollo-link-error : An Apollo Link for error handling

: An Apollo Link for error handling apollo-link-state : An Apollo Link for local state management

: An Apollo Link for local state management graphql-tag : Exports the gql function for your queries & mutations

Compare the following npm commands without and with apollo-boost.

# Without apollo-boost

npm install apollo-client apollo-cache-inmemory apollo-link-http apollo-link-error apollo-link --save # With apollo-boost

npm i apollo-boost graphql react-apollo@beta -S

This makes it easy since we manage less packages.

I hope this keeps you informed on client side implementation of GraphQL.

I will appreciate a clap, positive feedback and and criticism. I’m currently also keeping up with the Graphcool community and will be posting any updates with any major changes.