arrow left
Back to Developer Education

How to Create a Basic Browser GraphiQL Tool using React.js, Node.js and MongoDB

How to Create a Basic Browser GraphiQL Tool using React.js, Node.js and MongoDB

GraphQL is a query language for APIs used to communicate data between a client and a server. This allows you to structure data-driven applications much more flexibly and efficiently than the REST and SOAP approach. <!--more--> GraphQL provides a complete and understandable description of the data in your API. It gives clients the power to ask for exactly what they need and nothing more.

This makes it easier to evolve APIs over time and enables powerful developer tools. It also gives developers more control over how they use data in their apps.

GraphQL is an interactive development environment, featuring many GraphiQL graphical services that allow you to interact with your app data and GraphQL APIs.

We will create a basic browser GraphIQL tool featuring React.js, Node.js, and MongoDB.

Table of contents

Prerequisites

To follow along, you need:

Overview

Whenever you create a GraphQL API, GraphQL provides an extendable playground to execute and a GraphQL schema for the generated API. However, take a scenario where you have a CMS such as WordPress. You need to generate API data to separate the presentation layer.

In this case, an API plays a big role in helping users fetch data from the CMS. Therefore, you need to create a GraphQL interface that will allow these users to generate GraphQL-based queries.

This helps bridge modern frontend stacks with content management systems. GraphQL queries also allow you to access multiple root resources with a single request. Below is a basic example of a GraphQL tool.

query-posts-example

In this tutorial, we will build a similar GraphQL tool with React.js and demonstrate how to use it with a GraphQL API. Therefore, we need to create a GraphQL API that GraphiQL will use.

In this guide, we will create a simple GraphiQL using Node.js and MongoDB. A GraphQL API can be implemented using different technologies. If you have one running, you can skip this step.

Creating a Simple Node.js MongoDB GraphQL API

Create a Node.js server folder and change the directory to it:

cd server

Then initialize the Node.js project using npm init -y. To create this API, we need the following npm packages:

  • Express - A Node.js web framework for creating minimalistic HTTP servers.
  • GraphQL - Used to build GraphQL type schema and serve GraphQL queries.
  • Express-GraphQL - An Express-based HTTP web framework for creating GraphQL HTTP servers.
  • Mongoose - Provides MongoDB schema object modeling.
  • Body-parser - A parsing middleware used to handle request body properties.
  • CORS - To allow cross-origin resource sharing.

To install these packages, run the following command inside the server folder:

npm install express graphql express-graphql body-parser mongoose cors

Modeling the GraphQL data

To use a GraphQL API, we need to model the data using mongoose. This will set up the schema needed by the API to interact with the MongoDB database.

Create a post.js file inside the server folder and gete a post schema as follows:

const mongoose = require("mongoose");

const PostSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true
    },
    description: {
        type: String,
        trim: true
    },
});

const Post = mongoose.model("Post", PostSchema);

module.exports = Post;

Creating a GraphQL Post Schema

A GraphQL Schema defines GraphQL queries and mutations. A query in GraphQL is used to fetch data from the server, while mutation is used to manipulate data from the server. Mutations involve operations such as adding a post, updating post values, and deleting a post.

To create the GraphQL Post Schema, create a schema.js inside the server folder. Add the post model and the GraphQL entities required to create a GraphQL API.

const graphql = require('graphql');
const Posts = require('./post');

const {
    GraphQLObjectType,
    GraphQLList,
    GraphQLString,
    GraphQLSchema,
    GraphQLID,
} = graphql;

Set the GraphQL Object for the post. This represents how posts will be defined in the database.

const Post = new GraphQLObjectType({
    name: 'Post',
    fields: {
        id: {
            type: GraphQLID,
        },
        title: {
            type: GraphQLString,
        },
        description: {
            type: GraphQLString,
        },
    },
});

Create a query to get posts from the database.

const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
        posts: {
            type: new GraphQLList(Post),
            resolve(parent, args) {
                return Posts.find();
            },
        },
    },
});

Create a mutation to manipulate the database data.

const Mutation = new GraphQLObjectType({
    name: 'Mutation',
    fields: {
        addPosts: {
            type: Post,
            args: {
                title: { type: GraphQLString },
                description: { type: GraphQLString },
            },
            resolve(parent, args) {
                const post = new Posts({
                    title: args.title,
                    description: args.description,
                });
                return post.save();
            },
        },
    },
});

You can add other mutations for updating and deleting the post using the addPosts mutation as a reference.

Export the query and mutation so that we can use them within the server.

module.exports = new GraphQLSchema({
    query: RootQuery,
    mutation: Mutation,
});

Creating the server

To server, the above query and mutation, create a basic Node.js server. Create a server.js file inside the server folder and set up the server as follows:

  • Add the serve imports.
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const mongoose = require('mongoose');
const Posts = require('./post');
const schema = require('./schema');
var bodyParser = require('body-parser');
const cors = require('cors');
  • Create the server middleware.
// express
const app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));

// parse application/json
app.use(bodyParser.json());

//log body
main().catch((err) => console.log(err));
  • Establish a connection to the MongoDB database.
async function main() {
    const connect = await mongoose.connect(
        `mongodb://localhost:27017`,
        {
            useNewUrlParser: true,
            useUnifiedTopology: true,
        }
    );
    if (connect) {
        console.log('connected');
    }
}
  • Perform a basic CRUD operation with MongoDB. This tutorial only uses Create and Read operations for demonstration purposes.
// GET
app.get('/post', async (req, res) => {
    try {
        const postDetails = await Posts.find();
        res.send(postDetails);
    } catch (err) {
        console.log('~ err', err);
    }
});

// POST
app.post('/post', async (req, res) => {
    console.log('body', req.body);
    try {
        const newPost = new Posts(req.body);

        newPost.save(function (err, data) {
            if (err) {
                console.log(err._message);
            } else {
                res.send('Data inserted');
            }
        });
    } catch (err) {
        console.log('~ err', err);
    }
});
  • Execute the API GraphQL playground
app.use(
    '/graphql',
    graphqlHTTP({
        schema,
        graphiql: true,
    })
);
  • Start the server
app.listen(4000, () => {
    console.log('connected port 4000');
});
  • Run the server using node server.js. This will establish a connection to the database and execute the server on port 4000.

To test the server, you can open the GraphQL playground http://localhost:4000/graphql. Or use API testing utilities such as PostMan to send GET and Post requests to http://localhost:4000/post.

Using the PostMan Post method, add a few posts to the database as follows:

data

You can confirm if the data was successfully added to the database.

database

Creating the React App

We will use the above GraphQL API to integrate with a React GraphiQL tool. Let's dive in and create GraphiQL using React.js. First, we need to create a basic React app using the create-react-app command as follows:

npx create-react-app client

This command will create a React App. Change the directory to created client folder:

cd client

Starts the development server:

npm start

You can now view the created React app in the browser http://localhost:3000.

react-app

Installing Frontend packages

To create a GraphiQL tool, we need the following packages:

  • GraphQL - Used to build GraphQL type schema and serve GraphQL queries.
  • GraphiQL - It allows you to create in-browser GraphQL IDE to generate interactive GraphQL components for frontend frameworks.

Run the following command to install these packages.

npm install graphql graphiql

Creating and Rendering the GraphiQL UI with React

Let's create a UI for interactive GraphQL queries. Head to your React app src/app.js file and implement the GraphiQL tool as described in the following steps:

  • Import the dependencies and the peer dependencies as follows:
import React from 'react';
import GraphiQL from 'graphiql';
import { getIntrospectionQuery, buildClientSchema } from 'graphql';
import 'graphiql/graphiql.min.css';
  • Send requests to the server using fetch. In this case, make sure you add the GraphQL URL that executes the GraphQL route of your server.
const fetcher = async (graphQLParams) => {
  const data = await fetch(
    'http://localhost:4000/graphql',
    {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(graphQLParams),
      credentials: 'same-origin',
    },
  );
  return data.json().catch(() => data.text());
}
  • Create a class React component.
class App extends React.Component {
}

Inside this component, create a GraphiQL component as follows:

  • Define the state. Here, create the state for the GraphQL schema and query as follows:
_graphiql;
state = { schema: null, query: '# Hola!' };

_handleEditQuery = (query) => this.setState({ query });

componentDidMount() {
    this.updateSchema();
}
  • Execute the GraphQL from the server and sever the result of the server JSON response.
executeQuery = async (graphQLParams) => {
    const response = await fetch('http://localhost:4000/graphql', {
        method: 'POST',
        headers: {
            Accept: 'application/json',
            'Content-Type': 'application/json',
        },
        credentials: 'same-origin',
        body: JSON.stringify(graphQLParams),
    });

    const result = await response.json();
    return result;
}
  • Using an async method, Fetch the schema from the response result executed by the executeQuery function. In this case, create an async method and fetch the schema inside a try and catch block as follows:

Create the updateSchema() funtion

async updateSchema() {
    try {
    }
}

Inside this function, try block fetch the schema using introspection query.

const { data } = await this.executeQuery({ query: getIntrospectionQuery() });

Use the data we got back from GraphQL to build a client schema.

const schema = buildClientSchema(data);

Update our component with the new schema.

this.setState({ schema });

Log any errors.

this.setState({ error: null });

Finally, close the catch block inside updateSchema() to catch errors as follows:

catch (error) {
    console.error('Error occurred when updating the schema:');
    console.error(error);
    this.setState({ error });
}
  • Render the GraphQL data on the browser. This references the _graphiql and fetches the execute the GraphQL requests from the server.

Additionally, you can add the Prettify, History, and Explorer toolbar to GraphiQL. Here they are represented as dummies. Go ahead and implement them if your GraphiQL needs such functionalities.

render() {
    return (
        <div className="graphiql-container">

            <GraphiQL
                ref={ref => (this._graphiql = ref)}
                fetcher={fetcher}
            >
                <GraphiQL.Toolbar>
                    <GraphiQL.Button
                        title="Prettify Query (Shift-Ctrl-P)"
                        label="Prettify"
                    />
                    <GraphiQL.Button
                        label="History"
                        title="Show History"
                    />
                    <GraphiQL.Button
                        label="Explorer"
                        title="Construct a query with the GraphiQL explorer"
                    />
                </GraphiQL.Toolbar>
            </GraphiQL>
        </div>
    );
}
  • Finally, export the App component.
export default App;

Testing

Let's test if this tool is working as expected. At this point:

  • Enure your Node.js server is running and described in the previous steps
  • Ensure the React app is running and open the app in the browser using the URL http://localhost:3000. You will be served with the GraphiQL tool we have just created.

graphiql-tool

Let's test if the React GraphiQL tool can interact with the API data. We will execute a query to fetch posts from the database as follows:

query Query {
  posts {
    title
    description
  }
}

Add this query to the GraphiQL tool.

query

Then press the play button.

query-data

And there you have it. The frontend tool you created can directly interact with your server, deploy it, and allow users to interact with the content managed by your API.

Conclusion

GraphQL uses a mechanism that queries data and then displays that data with the GraphQL schema. This uses GraphiQL. You might want to query data from your application. A good example is how WordPress uses wpGraphQL to fetch WordPress-driven data.

In this guide, we learned how to create a GraphiQL tool to perform diffrent GraphQL tasks. This provides extendable GraphQL features within your application.


Peer Review Contributions by: Wanja Mike

Published on: Apr 5, 2023
Updated on: Jul 23, 2024
CTA

Start your journey with Cloudzilla

With Cloudzilla, apps freely roam across a global cloud with unbeatable simplicity and cost efficiency