Consuming a GraphQL API using Fetch and Async/Await
I was working on a small side project where I wanted to consume a GraphQL API. Before this, I hadn't worked with GraphQL much, other than configuring it which you can read about here. I knew there were libraries like Apolo, but I wanted to learn how to use a normal XHR request to consume a GraphQL API.
For the project I used React, but this will work with any JavaScript library/framework - provided you're using ES6.
Let's say you have a basic React component that is meant to load a list of movies within it's componentDidMount
function.
import React from "react";
export class MovieList extends React.Component {
state = {
movieList: []
};
componentDidMount() {
// Fetch movies from GraphQL endpoint here
}
render() {
// render movies
}
}
First, let's load up our GraphQL API into a playground to see what we will be querying. The playground I'll be using is FireQL.
In the playground, I'm going to use the searchMovies
query that accepts a movie title and returns a list of movies. I've selected the follow fields to be returned:
The FireQL playground then gave me the following query:
{
searchMovies(query: "endgame") {
id
title
releaseDate
overview
}
}
Great! This is the query that we need to use within our React component.
First we will create a function that will accept a movie title and return the appropriate GraphQL string:
getMoviesByTitleQuery = (movieTitle) => {
return JSON.stringify({
query: `
{
searchMovies(query: "${movieTitle}") {
id
title
releaseDate
overview
}
}
`
});
};
Now we're gonna create a function that accepts a GraphQL query body and uses Fetch to retrieve the result from the API.
performQuery = async(query) => {
const res = await fetch("YourGraphQLEndpointHere/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
query
});
return await res.json();
};
Finally, all we have to do now is use the two functions we created in one more function:
queryMoviesByTitle = async(movieTitle) => {
if (!movieTitle) {
return [];
}
const movieQueryBody = this.getMovieSummaryByTitleQuery(movieTitle);
const res = await this.performQuery(movieQueryBody);
return res.data.searchMovies;
};
Now use the queryMoviesByTitle
function in componentDidMount
and everything together will look like:
import React from "react";
export class MovieList extends React.Component {
state = {
movieList: []
};
componentDidMount() {
const movieList = await this.queryMoviesByTitle(query);
this.setState({ movieList });
}
queryMoviesByTitle = async(movieTitle) => {
if (!movieTitle) {
return [];
}
const movieQueryBody = this.getMoviesByTitleQuery(movieTitle);
const res = await this.performQuery(movieQueryBody);
return res.data.searchMovies;
};
getMoviesByTitleQuery = (movieTitle) => {
return JSON.stringify({
query: `
{
searchMovies(query: "${movieTitle}") {
id
title
releaseDate
overview
}
}
`
});
};
performQuery = async (query) => {
const res = await fetch("YourGraphQLEndpointHere/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
query
});
return await res.json();
};
render() {
const { movieList } = this.state;
return (
<div className="movie-list-container">
{movieList.map(movie => (<div>{movie.title}</div>)}
</div>
);
}
}
Great, now you have a function request to your GraphQL API and also some reusable functions that you can use for more of your GraphQL queries!