June 7, 2017

Building React Apps with GraphQL, Graphcool & Apollo

Graphcool

Graphcool

It’s been less than two years since Facebook first open-sourced GraphQL as a new way of exposing data from an API. In that short period, it’s already revolutionized the API space and many major companies, like GitHub, Twitter and Yelp, have started using it in production.

In this article, you’ll learn how to quickly get started with React & GraphQL by using Apollo Client and Graphcool to building a simple Instagram app. You can find the final version of the code on GitHub.

To follow along, grab the starter code and prepare yourself for some GraphQL awesomeness:

git clone https://github.com/graphcool-examples/react-graphql.git
cd react-graphql/quickstart-with-apollo

Creating a GraphQL Server

Since GraphQL has only been released as a specification, the burden is on the developer to implement their own GraphQL servers if they want to benefit from this new technology. Tools like Apollo Launchpad or graphql-up make it easy to spin up GraphQL APIs, but are not intended for production use. In this tutorial you’ll use Graphcool, a serverless GraphQL platform, to build a production-ready GraphQL backend.

The first thing you need to do is install the Graphcool CLI:

npm install -g graphcool

The CLI allows you to manage your project locally rather than using the web-based Console.

Every GraphQL API is based on a schema that defines the data model of the application. Here’s what the schema looks like for our Instagram app, expressed in the GraphQL SDL syntax:

type Post {
  description: String!
  imageUrl: String!
}

Using the Graphcool CLI to build your Backend

You can now create your GraphQL backend by referring to this schema that’s stored at a remote url:

graphcool init --schema https://graphqlbin.com/instagram.graphql --name Instagram

This command produces two endpoints — for the purpose of this tutorial you’ll use the one for the Simple API. It also creates a file called project.graphcool that contains all the configurations for your GraphQL backend and that enables you to make changes from the comfort zone of your terminal.

If you want to explore the capabilities of your API, you can open up a GraphQL Playground that allows you to send queries and mutations in an interactive manner. Simply type the following command in a terminal:

# in the directory where project.graphcool is located
graphcool playground

Connecting the App with the GraphQL Backend

The app is already completely implemented, so you don’t have to write any code to get started. However, you still need to configure the ApolloClient instance with the information about the server you just created.

Open ./src/index.js and replace the placeholder __SIMPLE_API_ENDPOINT__ with the endpoint for your Simple API. If you lost the endpoint, you can use the graphcool endpoints command in the terminal to see it again.

That’s it, you can now go ahead and use the app already:

yarn install
yarn start

Here’s what it looks like:

Exploring the Code

Let’s understand how the app works by exploring the ListPage and CreatePage components.

ListPage.js

This is the initial component of the app and will display all the posts that are currently stored in the backend.

At the bottom of the file, we define the FeedQuery that’s responsible for fetching all the posts from the API. With Apollo, it’s super easy to access the response data from a query in a React component. You can use the graphql higher-order component to wrap your component with the query:

const FeedQuery = gql`query allPosts {
  allPosts(orderBy: createdAt_DESC) {
    id
    imageUrl
    description
  }
}`

const ListPageWithData = graphql(FeedQuery)(ListPage)

The ApolloClient instance will then fetch the data for you behind the scenes and pass it down into the props of your component. In our case, we use the fetched posts in render:

{this.props.data.allPosts.map(post => (
  <Post
    key={post.id}
    post={post}
    refresh={() => this.props.data.refetch()}
  />
))}

Apollo Client has full control over the network request that’s happening when data is fetched. However, it’s a common use case to display a loading state on the UI whenever a network request is running.

That’s why Apollo also injects a loading property into your component’s props which provides precisely that information. We use it to render a loading state while data is being requested from the server:

if (this.props.data.loading) {
  return (
    // render loading element
  )
}

CreatePage.js

CreatePage is the component that we use to create a new post in the backend. Similar to the FeedQuery, we define a mutation and then wrap the CreatePage component with that mutation using the graphqlhigher-order component again. This makes the mutation available in the props of the component:

const addMutation = gql`
  mutation addPost($description: String!, $imageUrl: String!) {
    createPost(description: $description, imageUrl: $imageUrl) {
      id
      description
      imageUrl
    }
  }
`
const PageWithMutation = graphql(addMutation, {name: 'addPost'})(CreatePage)

The name that we specified refers to the field that gets injected into the props, we can thus invoke the mutation as follows:

const {description, imageUrl} = this.state
await this.props.addPost({variables: {description, imageUrl}})

Bonus: GraphQL Subscriptions

GraphQL Subscriptions only recently became part of the official GraphQL Spec. It’s a feature that lets you bring realtime functionality to an app by subscribing to specific events that are happening in the backend.

A subscription follows the same syntactical structure as queries and mutations, but you need to use the subscription keyword. Here’s an example for a subscription that will be triggered every time a new Post is created:

subscription {
  Post(filter: {
    mutation_in: [CREATED]
  }) {
    node {
      id
      description
      imageUrl
    }
  }
}

The node field contains the information about the newly created Post.

Subscriptions also work in GraphQL Playgrounds.

With Apollo Client, it’s easy to use subscriptions! First, you’ll need to add a new dependency to the project:

yarn add subscriptions-transport-ws@0.6.0

Note: Version 0.6.0 (or lower) is required because later versions are incompatible with the Graphcool Subscriptions API at the moment.

Then you need to adjust the configuration of the ApolloClient since it now also needs to be aware of the subscription server’s URL. This is what a typical setup looks like:

import { SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws'
import { ApolloClient, createNetworkInterface } from 'react-apollo'
const networkInterface = createNetworkInterface({
  uri: 'https://api.graph.cool/simple/v1/__PROJECT_ID__' // Your GraphQL endpoint
})
// Create WebSocket client
const wsClient = new SubscriptionClient('wss://subscriptions.graph.cool/v1/__PROJECT_ID__', {
  reconnect: true
})
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
  networkInterface,
  wsClient
)
const apolloClient = new ApolloClient({
  networkInterface: networkInterfaceWithSubscriptions
})

With this setup in place, you can now start subscribing to events. For example, you could subscribe to new posts being added in ListPage. Since you only want to subscribe once, this code can be placed in componentDidMount:

const NewPostsSubscription = gql`
subscription {
  Post(filter: {
    mutation_in: [CREATED]
  }) {
    node {
      id
      imageUrl
      description
    }
  }
}`

class ListPage extends React.Component {
  // ...
  componentDidMount() {
    this.subscription = this.props.data.subscribeToMore({
      document: NewPostsSubscription,
      updateQuery: (previousState, {subscriptionData}) => {
        const newPost = subscriptionData.data.Post.node
        return {
          allPosts: [
            {...newPost},
            ...previousState.allPosts
          ]
        }
      },
      onError: (err) => console.error(err),
    })
  }
 
  // ...
   
}

The updateQuery function that is passed as an argument works in the same way as a Redux reducer in that it lets you merge the new data into the Apollo store.

Conclusion

GraphQL is becoming the new standard in the API space. In this tutorial you learned how to get started with React & GraphQL by building a simple Instagram app.

If you want to learn more about what you can do with a Graphcool backend, check out some of the advanced features or a quick walkthrough of the whole platform. Make sure to subscribe to the GraphQL Weekly newsletter to stay up-to-date about everything that’s happening in the GraphQL community!

Written by

Graphcool

Graphcool

Read more by Graphcool