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.
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:
// 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:
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 theApolloProvider
component for providing anApolloClient
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:
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.
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)
Was planning on beginning to use graphQL today or the day after - exactly the read I needed. Thank you for the post Brian