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!