DEV Community

Cover image for GraphQL + React for noobs
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

GraphQL + React for noobs

Written by Ebenezer Don✏️

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

LogRocket Free Trial Banner

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
}
Enter fullscreen mode Exit fullscreen mode

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"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

// 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"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 }));
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Next:

create-react-app react_graphql
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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'
})
Enter fullscreen mode Exit fullscreen mode

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')
);
Enter fullscreen mode Exit fullscreen mode

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')
);
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

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
    }
  }
}`
Enter fullscreen mode Exit fullscreen mode

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>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

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, tracking slow network requests and component load time, try LogRocket.

Alt Text

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 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 — start monitoring for free.


The post GraphQL + React for noobs appeared first on LogRocket Blog.

Top comments (1)

Collapse
 
fly profile image
joon

Was planning on beginning to use graphQL today or the day after - exactly the read I needed. Thank you for the post Brian