Ebenezer Don Full-stack software engineer with a passion for building meaningful products that ease the lives of users.

GraphQL + React for noobs

6 min read 1836

GraphQL And React For Noobs

GraphQL is becoming the new standard for data-driven applications. It is an open-source data query and manipulation language for APIs, and a revolutionary way of thinking about communication between our client and the server.

In its own words:

GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.

After being made publicly available by Facebook in 2015, it has since become a strong alternative to the REST API architecture.

To start using GraphQL in your React application, you’ll need to understand the following terminologies:

  • Queries
  • Mutations
  • Clients

GraphQL queries

A GraphQL query is similar to a GET request in the REST API architecture. Queries are used to fetch or retrieve data from a GraphQL server. They are what determines the structure of our received data; this means that, as a user, you can request exactly what you want and how you want it structured. GraphQL queries are usually enclosed in braces:

{
  query_fields
}

The query fields are keys that reference specific data on our server. These data have types like string, int, float, Boolean, ID, or object. Here’s an example of a GraphQL query and its corresponding result:

// query
{
  article(slug: "5-amazing-math-tricks-flyingturtle") {
    title
    description
    author {
      name
      country
    }
  }
}


// result
{
  "data": {
    "article": {
      "title": "5 Amazing Math Tricks",
      "description": "here's what no one told you",
      "author": {
        "name": "Flying Turtle",
        "country": "Nigeria"
      }
    }
  }
}

In our example, notice how the result has the same structure as the query. If we had placed the description before the title in our query, we’ll get our result in the same order. The parenthesis after article on line 3 of our first block is what houses the query params. For this query, we provided the article slug as the unique identifier for the particular article we need from our GraphQL server.

It is also important to note that on line 6 of our first block, the author field has an Object type. When this is the case, we’ll also need to specify the fields we want from the object — in this case, name and country.

GraphQL mutations

When comparing GraphQL mutations to the REST API architecture, they are similar to PUT, PATCH, POST, and DELETE methods. A mutation, just like its name suggests, is a request that modifies the data on our GraphQL server. It can be used to update, insert, or delete data.

The syntax for mutations in GraphQL is similar to that of the fetch query, only that this time, we’ll add the mutation keyword before our first opening curly brace, and then pass in the fields we want to mutate and their values as parameters:

We made a custom demo for .
No really. Click here to check it out.

// mutation
mutation {
  updateArticle(slug: "5-amazing-math-tricks-flyingturtle", title: "just right") {
    title
    description
    author {
      name
      country
    }
  }
}


// result
{
  "data": {
    "article": {
      "title": "just right",
      "description": "here's what no one told you",
      "author": {
        "name": "Flying Turtle",
        "country": "Nigeria"
      }
    }
  }
}

If you noticed, we also specified the return values in our mutation request. This tells the GraphQL server exactly what to return to us after carrying out our request.

GraphQL clients

GraphQL clients enable us to send API requests to our GraphQL server. An example of a GraphQL client is curl from our command line:

curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "graphql_query"}' \
url_to_graphql_server

We can also use the JavaScript fetch API for making API calls to our GraphQL server:

fetch('url_to_graphql_server', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({query: "graphql_query"})
})
  .then(res => res.json())
  .then(data => console.log({ data }));

These methods look straightforward, but they could get complicated and might require a ton of avoidable code when we start dealing with more complex queries, state management, and caching.

Fortunately, there are more robust GraphQL clients like Apollo and Relay that are built to handle complex queries, caching, and effective state management in our React applications.

Here’s how the Apollo Client documentation describes Apollo:

Apollo Client is a complete state management library for JavaScript apps. Simply write a GraphQL query, and Apollo Client will take care of requesting and caching your data, as well as updating your UI.

The best way to understand GraphQL is by using it. Let’s learn how to use GraphQL with React by building a demo app that uses the Apollo Client to consume a GraphQL article API.

Building a react app with GraphQL

We’ll start by using create-react-app to bootstrap a new React application. If you don’t have create-react-app installed, on your terminal, run:

npm i -g create-react-app

Next:

create-react-app react_graphql

This will bootstrap a React application in a new directory named react_graphql. To start our application, we’ll navigate to our new directory from our terminal and run npm start:

cd react_graphql
npm start

If you’ve done everything right, a page like this should open in your browser:

Our Bootstrapped React App WIth GraphQL

Setting up GraphQL

To get started with GraphQL in React, we’ll need to install the following packages:

  • graphql
  • apollo-boost, which sets up our Apollo Client
  • react-apollo, which includes the ApolloProvider component for providing an ApolloClient instance to our GraphQL components

Let’s run the following command on our terminal:

npm i -s graphql apollo-boost react-apollo

This should install the packages in our application and add them to our project’s dependency.

Next, we’ll set up our application to process GraphQL queries from our root index file. In our /src/index.js file, we’ll start by importing ApolloClient and ApolloProvider from the apollo-boost and react-apollo packages, respectively. Let’s replace what we currently have in the /src/index.js file with the following code block:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import App from './App';

Next, we’ll set up our GraphQL client. To do this, we’ll create an instance of the ApolloClient and pass in a uri property. This is where we’ll be providing our GraphQL endpoint:

// src/index.js
...
const client = new ApolloClient({
  uri: 'https://awesome-node-graphql.herokuapp.com/graphql'
})

For the purpose of this article, I’ve built a GraphQL server with Node and Express.js (here’s a link to the GitHub repo). We’ll be able to get data for our article app by sending a query to the GraphQL API.

Now that we’ve set up our GraphQL client, let’s connect it to our React application. We’ll do this by wrapping our App component in the ApolloProvider we imported earlier and then supplying our provider with a client prop:

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

Our /src/index.js file should now look like this:

import React from 'react';
import ReactDOM from 'react-dom';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import App from './App';

const client = new ApolloClient({
  uri: 'https://awesome-node-graphql.herokuapp.com/graphql'
})

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

Fetching data with the query component

Next, we’ll use the Query component from react-apollo to consume our GraphQL endpoint. When calling the Query component, we’ll pass in our GraphQL query as its prop. First, let’s replace what we currently have in our /src/App.js with the following code block:

// src/App.js
import React from 'react';
import { Query } from 'react-apollo';
import { gql } from 'apollo-boost';

Here, we’ve imported the Query component from react-apollo and gql from apollo-boost. The gql template literal tag parses GraphQL query strings into the standard GraphQL abstract syntax tree. Let’s declare a variable, getAllArticles, and assign it our GraphQL query:

// src/App.js
...
const getAllArticles = gql`{
  articles {
    title
    description
    coverImageUrl
    author {
      name
      country
    }
  }
}`

Next, we’ll create our App component and, in it, call the Query component from react-apollo. The Query component uses React’s render prop pattern and returns an object from the Apollo client containing the following properties:

  • loading: Returns a Boolean value based on the request status
  • error: Returns an error message if our request is unsuccessful
  • data: Returns the requested data from our server

Let’s add the following block to our src/App.js file:

// src/App.js
...
const App = () => {
  return (
    <>
      <Query query={getAllArticles}>
        {({ loading, error, data }) => {
          if (loading) return <p>Relax, it's worth the wait...</p>
          if (error) return <p>Looks like we've got a problem...</p>
        }}
      </Query>
    </>
  );
}

Populating our page with the fetched data

To populate our page with the fetched data, we’ll use the JavaScript map function to iterate our data. Our final /src/App.js file should look like this:

import React from 'react';
import { Query } from 'react-apollo';
import { gql } from 'apollo-boost';

const getAllArticles = gql`{
  articles {
    title
    description
    coverImageUrl
    author {
      name
      country
    }
  }
}`

const App = () => {
  return (
    <Query query={getAllArticles}>
      {({ loading, error, data }) => {
        if (loading) return <p>Relax, it's worth the wait...</p>
        if (error) return <p>Looks like we've got a problem...</p>
        return (
          <div className="container">
            <h1>Articles</h1>
            <div className="row">
              {data.articles.map(article => (
                <div className="col-sm">
                  <div className="card" style={{width: "18rem"}}>
                    <img
                      src={article.coverImageUrl}
                      className="card-img-top"
                      style={{height: "10em"}}
                      alt="cover"
                    />
                    <div className="card-body">
                      <h5 className="card-title">{article.title}</h5>
                      <p className="card-text">{article.description}</p>
                      <button className="btn btn-primary">Read</button>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>
        )
      }}
    </Query>
  );
}

export default App;

Finally, let’s add the Bootstrap CDN to our /public/index.html file for our app’s CSS styling. We’ll paste the following <link> tag before the <title> tag definition:

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" 
      integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" 
      crossorigin="anonymous">

When we start our application and navigate to localhost:3000/ in our browser, we should see a similar page to this:

Final App Preview

Conclusion

In this article, we’ve learned the basics of GraphQL and how to use it in our React applications. Of course, GraphQL won’t replace the REST architecture immediately, as it will be difficult to rewrite all the existing platforms overnight, but it eventually will.

GraphQL solves a whole lot of problems for data-driven applications, including the overfetching and underfetching of information. It makes complex queries relatively easy to write and gives clients the power to ask for exactly what they want.

Here’s a link to the GitHub repository for our demo app. Feel free to reach out to me via Twitter if you need any further assistance on GraphQL and React.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Ebenezer Don Full-stack software engineer with a passion for building meaningful products that ease the lives of users.

2 Replies to “GraphQL + React for noobs”

  1. Thanks for this article, Ebenezer. In recent months I’ve been using axios to make traditional API calls. Now, on a personal project of my own, I’m going to try using GraphQL. Sounds like you’re a proponent of using the Apollo Client? Quick question: With Apollo installed, what do you use for non-local state management? I’ve read that Apollo can be used as as substitute for the Context API and Redux. My recent experience has been with the Context API. I wonder if it makes sense to have an app with both Apollo and the Context API?

  2. Hi Robert, I’m glad you found this helpful. I think to a great extent, choosing a state management tool boils down to personal choice.

    In this case, I think using the Apollo cache would be easier. You might want to check out this article on Managing Local State with Apollo Client and React Hooks: https://itnext.io/managing-local-state-with-apollo-client-and-react-hooks-9ad357e6d649

    I also have an article on React Hooks and the Context API where I tried making the UseContext setup as straightforward as I can: https://blog.logrocket.com/use-hooks-and-context-not-react-and-redux/

Leave a Reply