Bite-sized screencasts for React
and frontend developers

Introduction to using GraphQl in React with Apollo

posted on: 08-may-2018

What is GraphQl and why should I be interested in it? In a nutshell, we can see GraphQL as a syntax that describes the data you get, usually from a backend API. It was created by Facebook and in most cases, it provides good solutions to REST API's problems.

For this tutorial, the scope is to get up and running with a React application that uses Apollo to interact with a GraphQl endpoint. We will go intro more details in other articles, but for now the idea is to understand and "feel" the general workflow in GraphQl.

We will build a very simple movie application, that will interact with some data from a GraphQl endpoint. You can see it in the below image.

graphql react example

Installing GraphQl and Apollo

To get started we will need to add bunch of libraries to our project. If you want you can use create-react-app. Create a React app then open up a console and type:

npm i -save react-apollo graphql-tag apollo-boost

As very short run through:

  • react-apollo is the connector that links React to GraphQl. An alternative to it is Relayjs.
  • graphql-tag will be useful to write the GraphQl queries
  • and from the apollo-boost we will use the ApolloClient as the main bridge to the GraphQl endpoint

From a code perspective, we will first need to create an instance of the ApolloClient client. The ApolloClient will need the uri of the GraphQl endpoint.

import ApolloClient from "apollo-boost"

//...
const client = new ApolloClient({
  uri: "https://r9v94p7kqn.lp.gql.zone/graphql"
})

After having the ApolloClient instance ready, we will then wrap the main app content with an ApolloProvider:

import { ApolloProvider} from "react-apollo"
//...
class App extends Component {
  render() {
    return (
      <ApolloProvider client={client}>
          <Movies />
      </ApolloProvider>
    );
  }
}

Seting up a Javascript - GrapQl endpoint

You may have noticed the uri: "https://r9v94p7kqn.lp.gql.zone/graphql" from the ApolloClient constructor. If you leave out the /graphql and visit the link https://r9v94p7kqn.lp.gql.zone you will see the graphql launchpad that contains our endpoint.

javascript graphql launchpad

Without going too deep into details our endpoint has a

  1. a schema definition that describes how a basic movie data will look like, but also what type of data the queries will return:

    // Construct a schema, using a GraphQL schema language
    const typeDefs = `
    type Query {
    allMovies: [Movie]
        movie(id: Int!): Movie
    },
    type Movie {
        id: Int
        title: String
        director: String
        actors: [String]
        poster: String
        year: Int
    }
    `;
  2. and also, a set of data + resolver functions that will be used when a query takes place:

var moviesData = [
    {
        id: 1,
        title: 'The Godfather',
        director: 'Francis Ford Coppola',
        actors: ['Marlon Brando', 'Al Pacino', 'James Caan'],
        poster: 'https://ia.media-imdb.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY268_CR3,0,182,268_AL_.jpg',
        year: 1972
      }
      //...
];

var getMovie = function(root, {id}) { 
    return moviesData.filter(m => {
        return m.id === id;
    })[0];
};

var getAllMovies = function() {
  return moviesData;
}

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    allMovies: getAllMovies,
    movie: getMovie,
  },
};

// Required: Export the GraphQL.js schema object as "schema"
export const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

In this example, we have used Javascript, but you can setup GraphQl endpoints with any major programming language. Please note, that the core data - moviesData array - should usually come from a database. We just used this static array for simplicity purposes.

Making the first GraphQl query with React - Apollo

There are multiple ways to query a GraphQl endpoint. To list the basic info of the movies we will use the Query component from react-apollo:

import { Query, ApolloProvider } from "react-apollo";
//...
const Movies = () => (
  <Query
    query={gql`
      {
        allMovies {
          id
          title
          poster
          actors
        }
      }
    `}
  >
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;
      return data.allMovies.map(movie => (
        <div className="movie">
          <h3>{movie.title}</h3>
          <p>{JSON.stringify(movie.actors)}</p>
        </div>
      ));
    }}
  </Query>
); 

Using the parameters loading, error, data that we get access to in the child function, we can control how the layout looks like when the data is still loading or when we get an error response. At this point the complete code and app looks like this:

By the way, if you would like to get more articles about React and GraphQl you can always subscribe to my email list.

Triggering a GraphQl query on a React UI event

But what if we wanted to trigger a query on a specific UI event, like a button click? For example, if we wanted to get the complete details for a movie when a Get all details button is pressed.

react graphql button query

First let's extract a Movie component:

class Movie extends Component {
  getDetails = ()=> {
   // will make the GrahQl here
  }

  render() {
    return(
        <div className="movie">
          <img src={this.props.data.poster} />
          <div className="details">
            <h3>{this.props.data.title}</h3> 
            <p>{JSON.stringify(this.props.data.actors)}</p>
            <button onClick={this.getDetails}>Get all details</button>
          </div>
        </div>
    )
  }
}

//...

const Movies = () => (
    {({ loading, error, data }) => {
    //...
return data.allMovies.map((movie) => (
<Movie key={movie.id} data={movie} />
));
    }}
);

Now, to manually trigger the GraphQl Query we will need access to the ApolloClient instance in the Movie component. All the components that are descendants of the ApolloProvider can gain access to the client instance by using the withApollo() helper function:

import { Query, ApolloProvider, withApollo} from "react-apollo";
//...
class Movie extends Component {
  //...
}
Movie = withApollo(Movie)

So now we can access the ApolloClient as a property of the Movie component, and use it to trigger the query call:

class Movie extends Component {
  getDetails = ()=> {
    this.props.client.query({
      query: gql`
        {
          movie (id:${this.props.data.id}) {
            id
            title
            director
            actors
            year
          }
        }
      `,
    }).then((data) => alert(JSON.stringify(data.data.movie,null,'\t')))
  }
  //...
}

You can play with the complete app in the bellow code sandbox:

I hope you enjoyed this article and realized is quite easy to get up and running with using GraphQl in React. This is just the tip of the iceberg, but hey ... every journey begins with a single step :).

By the way, if you would like to get more articles about React and GraphQl you can always sign up for my email list.