Fetching Data from a GraphQL API

It’s common to hear GraphQL described as a REST killer. Here to slash your REST services, to end your endpoints. But today, let’s not focus on conflict. Let’s consider where GraphQL and REST share something in common: HTTP requests.
That’s right. If you know how to send HTTP requests, you already have the tools necessary to build a client application that communicates with any GraphQL API. We can get data using any method that sends an HTTP request. Let’s build a tiny client by using fetch, which will work in the browser:
const query = `
query {
Lift(id: "panorama") {
name
status
}
}
`;const url = "https://snowtooth.moonhighway.com/";const opts = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query })
};fetch(url, opts)
.then(res => res.json())
.then(console.log)
.catch(console.error);
We’ll send the fetch request with some options. Then we’ll convert the response to JSON. When we log the results to the console, we’ll see the following:
results
{
"data": {
"Lift": {
"name": "Panorama",
"status": "HOLD"
}
}
}
You could even display your results on an HTML page by replacing the console log
with some simple DOM manipulation:
fetch(url, opts)
.then(res => res.json())
.then(
({ data }) => `
<p>
Favorite Lift: ${data.Lift.name}
Status: ${data.Lift.status}
</p>
`
)
.then(text => (document.body.innerHTML = text))
.catch(console.error);
Mutations with fetch
Whenever we want to change data, we’ll use a GraphQL mutation. Our API supports a mutation called setLiftStatus
. This mutation takes in the id of the Lift
you want to change and the new status
for that lift. The options for LiftStatus
are a GraphQL enum, a restricted list of options for a specific field. These options are OPEN
, CLOSED
, and HOLD
. Start by defining the setLiftStatus
mutation string as a variable:
const mutation = `
mutation {
setLiftStatus(id: "panorama", status: CLOSED) {
name
status
}
}
`;
Then we want to use the same GraphQL endpoint. We’ll adjust the body of the request to include the mutation:
var url = "https://snowtooth.moonhighway.com/";
var opts = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query: mutation })
};
Finally, we can send the request and log the results:
fetch(url, opts)
.then(res => res.json())
.then(console.log)
.catch(console.error);
And our results will reflect that the Panorama lift status has indeed been changed by the mutation:
results
{
"data": {
"Lift": {
"name": "Panorama",
"status": "CLOSED"
}
}
}
graphql-request
There are other frameworks that can be used to send GraphQL operations to an API. One of the most minimal examples of this is graphql-request
. GraphQL Request wraps fetch
requests in a promise that can be used to make requests to the GraphQL server. It also handles the details of making the request and parsing the data for you. graphql-request
is maintained by the team at Prisma.
To get started with graphql-request
, you will need to install it:
npm install graphql-request --save
From there, you’ll import and use the module as request
:
import { request } from "graphql-request";
const query = `
query {
Trail(id: "grandma") {
name
status
}
}
`;
request("https://snowtooth.moonhighway.com/graphql", query)
.then(console.log)
.catch(console.error);
The request function takes in url
and query
, makes the request to the server, and returns the data in one line of code. The data returned is, as expected, a JSON response of all of the users:
{
"Trail": {
"name": "Grandma",
"status": "OPEN"
}
}
Notice that the results here are a little bit different than the fetch
request. Instead of returning the data under the data
key, the request sent with graphql-request
returns just the object. If you wanted to use this data in your app, you would access that data off of the Trail
key.
ENJOY YOUR CODING!