Skip to main content

Command Palette

Search for a command to run...

Implementing GraphQL with React and Node

Published
6 min read
Implementing GraphQL with React and Node
M

Talking and consulting on MLOps and machine learning. https://www.linkedin.com/company/monika-mlops-consulting/

Introduction

GraphQL is a fast and modern way to fetch data to your application. It has many advantages, such as: caching, speed and unified data model. It sits between your backend and frontent:

image.png We will be implementing a very simple GraphQL use case for Node.js backend and React.js frontend.

Middleware and Backend

We'll use Apollo and Express server integration: apollo-server-express.

npm i create-react-app graphql apollo-server-express express

Create a folder for a server side:

mkdir server
code apollo_server.js

In the apollo_server.js file import the modules:

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');

Then construct a schema with GraphQL language for variables that you will be fetching. Define the type for variables, here it will be a string:

const typeDefs = gql`
  type Query {
    user: String,
    email: String
  }
`;

Now let's create some dummy data. We will later replace this with MongoDB data.

const test_user = 'jaguar'
const test_email = 'jaguar@gmail.com'

Let's use it and create Query resolvers:

const resolvers = {
  Query: {
    user: () => test_user,
    email: () => test_email,
  },
};

Now let's run Apollo Server and make it a middleware in front of our express server:

const server = new ApolloServer({ typeDefs, resolvers });

const app = express();
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

We can start the server with:

node apollo_server.js

The whole apollo_server.js file should look like this:

const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');

const typeDefs = gql`
  type Query {
    user: String,
    email: String
  }
`;

const test_user = 'jaguar'
const test_email = 'jaguar@gmail.com'

const resolvers = {
  Query: {
    user: () => test_user,
    email: () => test_email,
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

const app = express();
server.applyMiddleware({ app });

app.listen({ port: 4000 }, () =>
  console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

Now let's move on to the front-end.

Frontend

Let's create the folder and the starting application:

mkdir client
cd client
npm i -g create-react-app
create-react-app test_book
cd test_book
npm i @apollo/react-hooks apollo-boost
cd src
code index.js

Import the Apollo hooks, client and connect it to the server:

import { ApolloProvider } from '@apollo/client';
import ApolloClient from 'apollo-boost';

const client = new ApolloClient({
  uri: 'http://localhost:4000',
});

Add Apollo Client context to the App component:

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

The whole index.js file should look like this:

import { ApolloProvider } from '@apollo/client';
import ApolloClient from 'apollo-boost';

const client = new ApolloClient({
  uri: 'http://localhost:4000/graphql',
});

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

serviceWorker.unregister();

Now we will use useQuery hook to query data from the Apollo server. Open App.js:

const USER_QUERY = gql`
  {
    user
    email
  }
`;

Fetch the data, display whether the data was loading or an error happened:

const App = () => {
  const { loading, error, data } = useQuery(USER_QUERY);
  if (loading) {
    return <p>Loading...</p>;
  }
  if (error) {
    console.log(error)
    return <p>Error :(</p>;
  } 
  return (
    <div className="App">
      <header className="App-header">
        <p>
          User is: {data.user}
        </p>
        <p>
          Email is: {data.email}
        </p>
      </header>
    </div>
  );
}

You shoul see the data successfully loaded in the browser:

Screenshot from 2020-08-30 22-47-35.png The whole App.js file should be:

import React from 'react';
import './App.css';
import { useQuery } from '@apollo/react-hooks';
import { gql } from 'apollo-boost';

const USER_QUERY = gql`
  {
    user
    email
  }
`;

const App = () => {
  const { loading, error, data } = useQuery(USER_QUERY);
  if (loading) {
    return <p>Loading...</p>;
  }
  if (error) {
    console.log(error)
    return <p>Error :(</p>;
  } 
  return (
    <div className="App">
      <header className="App-header">
        <p>
          User is: {data.user}
        </p>
        <p>
          Email is: {data.email}
        </p>
      </header>
    </div>
  );
}

export default App;

Enjoy - you just made a successfull GraphQL query! In the following tutorial we will tailor our query to the full user model.

Let the good times roll!

D

It quite a nice introductory to GraphQL. However it quite resembles a simple fetch at the moment, I do not quite get the benefits of GraphQL, could you elaborate more?

1
M

Hello!

Sure. GraphQL replaces the need of multiple endpoints - you no longer need to code in each request. From this, for each data type (both client side and server endpoint wise):

fetch('https://localhost/posts/1') fetch('https://localhost/users/2')

=>

You simply connect to Apollo Server, describe query with gql and fetching is automatic.

In most cases data is updated automatically given it changes in the storing location. Also, there is data caching to make it faster.

Nevertheless, I think, the biggest advantage is the ease of development once you get used to. You can also follow the graph schema of your data in it's UI.

Best regards, Monika

1
D

Yep query the data without multiple endpoints implementation is a good reason why I might use GraphQL in future, thank you for sharing.

Monika Venčkauskaitė

1
M

Dinys Monvoisin Glad to hear that!

More from this blog

monika.ai

7 posts

Machine Learning and MLOps Engineer. Talks #machinelearning, #MLOps, , #python, #kubernetes, #terraform, #GCP and #VertexAI.