GraphQL

Create GraphQL Apollo Client using React Part 1

January 29, 2018

author:

Create GraphQL Apollo Client using React Part 1

Today we will work on the front-end to our Graphql API in Express with Apollo. We have already created the required API earlier. So to today, we will build front-end for it using React Js.

# GraphQL Apollo Client Installation in React

Create a fresh react project or clone this example from GitHub repo. Install the react-apollo and other libraries if you are working on your own project.

Npm install react-apollo react-dom react-router-dom --save

# React Folder Structure

As always, lets set the folder structure right from the beginning:

-src
  --app
    ---components 
      create_company.js    //CreateCompany component
      display_company.js   //Fetch single company
      list_company.js      //CompaniesList component
      update_company.js    //EditCompany component
   app.js    //root component
  --public
     index.html  //public root
  --style
      app.scss  //application styles
-node_modules //store installed packages
-package.json //store information about application and libraries
-webpack.config.js //webpack settings and configs

# Render Company List with GraphQL Data

Let us start with importing required libraries and react basic class scaffolding:

# src/app/components/list_company.js

import React, { Component } from 'react';
import { gql, graphql } from 'react-apollo';

GraphQL Apollo Query in React:

Let us now utilize the imported graphql elements. We will use them to bind our react component with GraphQL HOC (Higher Order Component) to execute a query and return data to the component.

# src/app/components/list_company.js

const CompanyListQuery = gql `
  query CompanyList{
    Companies {
      id
      name
    }
  }
`;

We can define queries and mutations with gql template tag in Apollo Client. Apollo parses the query and returns some methods to the Client. Due to HOC wrapping, the react component receives data, loading and error as props. Loading is especially useful when the execution is under process and data are being fetched. This reduces the headache of handling the state of the request. Thus we can utilize this props in our render method:

# src/app/components/list_company.js
...
class CompaniesList extends Component {
 render() {	
   const { loading, error, Companies }= this.props.data;
   if (loading) {
     return <p> Loading... </p>;
   }
   if (error) {
     return <p> { error.message } </p>;
   }	
   return (
     <div>
       <ul className = "list-group" > {
         Companies.map(c => <li className = "list-group-item" key = { c.id }> 
           <div className="post-list">
             <div className="post-title">
               <Link to = {`/company/${c.id}`}>
                 {c.name}
               </Link>
             </div>
           </div>
         </li> 
       ) } 
     </ul> 
   </div>
   );
 };
}

const CompaniesListWithData = graphql(CompanyListQuery )(CompaniesList);
export default CompaniesListWithData;

# Map GraphQL API in Main Component

The Main component will store various routes and other graphQL Apollo specific details like network interface that defines the HTTP connection with our API.

# src/app/app.js
...
const networkInterface = createNetworkInterface({
  uri: 'http://localhost:3000/graphql',
});

networkInterface.use([{
  applyMiddleware(req, next) {
    setTimeout(next, 1000);
  },
}]);

A configuration object can be provided with createNetworkInterface() to setup an HTTP network interface. It mostly includes the Graphql API URI that Apollo can interact with.

# GraphQL Apollo Client Integration in React

# src/app/app.js
...
<ApolloProvider client={client}>
  <div className="App">
    <div className="row">
      <div className="col-lg-6 col-lg-offset-3">
        <BrowserRouter>
          <div>
            <Switch>
              <Route path="/" component={CompaniesList} />
            </Switch>
          </div>
        </BrowserRouter>
      </div>
    </div>
  </div>
</ApolloProvider>,
app

ApolloProvider has a similar function to react-redux Provider. It is a higher order component that maps client instance to React component tree. As with ApolloProvider, it enables GraphQL components to use graphql function and use GraphQL API. However, Apollo cannot function, if we do not add this component to the root of the React component tree. We can also configure redux store with the client if necessary.

# src/app/app.js

import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { ApolloClient, ApolloProvider, createNetworkInterface } from 'react-apollo';

import CompaniesList from './components/list_company';
import '../style/app.scss';

const networkInterface = createNetworkInterface({
  uri: 'http://localhost:3000/graphql',
});

const client = new ApolloClient({
   networkInterface,
});

let app = document.querySelector('#app');

render(
<ApolloProvider client={client}>
  <div className="App">
    <div className="row">
      <div className="col-lg-6 col-lg-offset-3">
        <BrowserRouter>
          <div>
            <Switch>
              <Route path="/" component={CompaniesList} />				  
            </Switch>
          </div>
        </BrowserRouter>
      </div>
    </div>
  </div>
</ApolloProvider>,
app
)

We are using react-router-dom capabilities to add routes to our application. For now, we have only one route to view the list of company; we will add more routes as and when required.

# Testing React Apollo Application

Make sure the GraphQL API server is up and running in the background. If you don’t have the API, clone this repo from GitHub.

node server.js
GraphQL Apollo API Server running
http://localhost:8080/graphiql

React App URL:

http://localhost:8100
Data List in React App

# Insert in GraphQL API with Mutation

Mutations are used for insert, update and delete operation in GraphQL API. Let us wire a new react component to create new company in the application. Create a fresh file create_company.js in src/app/components if haven’t already.

# src/app/components/create_company.js

import React, { Component } from "react";
import { Link } from "react-router-dom";

class CreateCompany extends Component {
  constructor(props) {
    super(props);
    this.state = { name: "" };
    this.onNameChange = this.onNameChange.bind(this);
    this.onFormSubmit = this.onFormSubmit.bind(this);
} 

  onNameChange(event) {
    this.setState({ name: event.target.value });
  }

  onFormSubmit(event) {
    event.preventDefault();
    const { name } = this.state;
    console.log(name);
  }

  render() {	  
    return (
      <div>
        <h3> Add New Company </h3>
        <div className="form-holder">
          <form onSubmit={this.onFormSubmit}>
            <input
            type="text"
            className="form-control post-control"
            placeholder="Name"
            value={this.state.name}
            onChange={this.onNameChange}
            />

            <ul className='list-inline company-actions'>            
              <li><button type="submit" className='btn btn-primary'>Post</button></li>
              <li><Link to="/" className='btn btn-danger'>Cancel</Link></li>
            </ul>
          </form>
        </div>
      </div>
    );
  }
}

export default CreateCompany;

Here we are rendering a form with name input. We are also using the component level state to keep a track of user input with relevant event handler and binding them to the constructor using es6 syntax. Nothing fancy as of now.

GraphQL Apollo Mutation in React

Let us now instill graphql capabilities to this component.

# src/app/components/create_company.js
...
import { gql, graphql } from 'react-apollo';

class CreateCompany extends Component {
  ...
 }

const CreateCompanyMutation = gql`
  mutation addCompany($name: String!) {
    addCompany (name: $name){
      id
      name
    }
  }
`;

We are familiar with graphql mutation syntax. Here, we are using the gql template to add mutation schema. $name will come from user input on form submission:

# src/app/components/create_company.js
...
class CreateCompany extends Component {
  ...

  onFormSubmit(event) {
    event.preventDefault();
    const { name } = this.state;

    this.props.mutate({
      variables: { name }
    })
    .then(() => {
      this.setState({ name: "" });
      this.props.history.push("/");
    });
  }
}
...

In the submit handler binding mutation with mutate prop and passing required arguments in the variables. The addComany above gets user data from this mutate prop.

# src/app/components/create_company.js
...
const CreateCompanyWithMutation = graphql(
  CreateCompanyMutation
)(CreateCompany);

export default CreateCompanyWithMutation;

In the above export snippet, we are injecting graphql mutation to our CreateCompany component with the help of react-apollo package.

Here’s our complete CreateCompany component file:

# src/app/components/create_comapny.js

import React, { Component } from "react";
import { Link } from "react-router-dom";
import { gql, graphql } from 'react-apollo';

class CreateCompany extends Component {
  constructor(props) {
    super(props);
    this.state = { name: "" };
    this.onNameChange = this.onNameChange.bind(this);
    this.onFormSubmit = this.onFormSubmit.bind(this);
} 

  onNameChange(event) {
    this.setState({ name: event.target.value });
  }

  onFormSubmit(event) {
    event.preventDefault();
    const { name } = this.state;

    this.props.mutate({
      variables: { name }
    })
    .then(() => {
      this.setState({ name: "" });
      this.props.history.push("/");
    });
  }

  render() {	  
    return (
      <div>
        <h3> Add New Company </h3>
        <div className="form-holder">
          <form onSubmit={this.onFormSubmit}>
            <input
            type="text"
            className="form-control post-control"
            placeholder="Name"
            value={this.state.name}
            onChange={this.onNameChange}
            />

            <ul className='list-inline company-actions'>            
              <li><button type="submit" className='btn btn-primary'>Post</button></li>
              <li><Link to="/" className='btn btn-danger'>Cancel</Link></li>
            </ul>
          </form>
        </div>
      </div>
    );
  }
}

const CreateCompanyMutation = gql`
  mutation addCompany($name: String!) {
    addCompany (name: $name){
      id
      name
    }
  }
`;

const CreateCompanyWithMutation = graphql(
  CreateCompanyMutation
)(CreateCompany);

export default CreateCompanyWithMutation;

Let us also wire this component with react root component:

# src/app/app.js
...
import CreateCompany from './components/create_company';

...

render(
<ApolloProvider client={client}>
  ...
    <Switch>
      <Route path="/company/create" component={CreateCompany} />
      <Route path="/" component={CompaniesList} />				  
    </Switch>
  ...
</ApolloProvider>,
app
)

# Testing

It’s again time to test insert operation in React for GraphQL API. Hope your server is up and running.

http://localhost:8100
Insert in React Apollo GraphQL

Conclusion:

We started building a fresh react application to utilize the GraphQL API we created earlier. We created some components to render the company list and insert operations. In the next tutorial, we will complete the whole application.

Questions & Comments:

Thanks for stopping by. If you get stuck at any step or have questions/suggestions, shoot them right away in the comment section below.

Leave a comment

Your email address will not be published. Required fields are marked *