Third of three articles focused on building Fullstack React and GraphQL with the Apollo GraphQL Client.

Creating the React Application with an Apollo GraphQL client

The intent of this segment is not to teach React in entirety. Rather I will help you plug in the parts related to using Apollo GraphQL. I’ve done some setup ahead of time and included most of the React app that you will need in a repo. This premade code that we clone into our project will be a React project that was built with Create Rect App and has routing, navigation, menus, responsive behavior, state and context being managed as well as some utility and other components to support a basic app architecture. I wanted to make sure we only needed to worry about setting up the Apollo GraphQL client, but I wanted to do it in the context of a working application.

Clone an Existing React Application

Our decoupled React frontend will be a sibling to the couchbase-gql-server directory. here is a basic idea of what our directory structure will look like:

Let’s clone the starting point for our React project by running the following git command from the root (rage-with-couchbase directory) in our terminal:

In the command above, we removed the .git directory as we do not want to take on the existing git history from the project we cloned into our project. You will need to initialize git on your own and periodically commit if you want to. It’s encouraged so that you don’t lose your work.

We now have a working React application added to our project with basic routing. There are some components and utilities that exist in the React project but are not yet hooked up. Before we get to them, let’s run the React application on its own just to make sure everything is working with no errors:

preview of our React starting point

Open the console (⌘ Cmd + ⌥ Option + I on Mac) (Ctrl + ↑ Shift + J on PC)

Ensure that clicking back and forth from Home to Airlines does not generate any errors and that there are no errors or major warnings. What we see in this preview is the Airlines route, it is the route we will be adding our master-detail feature to. It’s like someone else already took care of all the styling and basic layout, our job will be to hook up the airline-list.jsx and airline-details.jsx file in place of the current placeholder text on each side of the page. Luckily our design team has ensured that all of the layout and CSS work is complete!

Before we make changes to the React app, let’s understand some of the files that we have in our project that are not yet in play with our Airline route.

Overview of Our Assets

There are 6 files we want to make ourselves familiar with that are standing by and awaiting our use.

A convention that we are using regarding directory structure is that components in the “routes” directory are React components that are resolved to form a specific route and those files inside of the “partial” directory are components that are not a view loaded by a route, but instead a partial view or a component that could potentially be reused in our application. This is a convention I use, not something React forces us to do.

withApolloProvider – I am using a higher-order component that I created so that I can wrap any component with a different GraphQL provider and endpoint if needed. Just understand that this is similar to importing the ApolloProvider in the parent component. This may not be a best practice, but I like that it keeps my code tidy. I’m open to suggestions on how to do this better.

We have airline-list.jsx and a airline-details.jsx, these two components will get loaded side by side in our airlines.jsx component. The list will simply display each airline and uses pagination.jsx to ensure we don’t have long list running down the left-side of the page.

Finally, we have the airline-gql.js file which is simply our GraphQL query for all UK Airlines. I like to separate my queries out into another file for organizational purposes, it’s not required, but it cleans up the airlines.jsx file.

How Our Master-Detail Page Works

In our project we have a master-detail component relationship (airline-list.jsx && airline-details.jsx), at the /airlines route. This route resolves to a view component named: airlines.jsx, which utilizes React Router’s capabilities to match not only the route but an additional URI parameter (airlineId) which we can append to the end of the route to be specific. When no specific airlineId URI parameter is present in the URL:

http://localhost:3000/airlines

It will only display a list of airlines on the left side. As well, a link will show up on the right side of the page that reads: “Select an airline”.

Selecting an airline from the menu will load the details on the right side of the page. Once clicked, we will update the URL with the proper id using a <Link /> component provided by React Router:

http://localhost:3000/airlines/1355

Here we will match the ID 1355 with the correct airline already in memory in our React application data and display its appropriate Airline information “British Airways”.

Adding Dependencies for our Apollo GraphQL client

We need three packages: @apollo/react-hooks, apollo-boost, and graphql,brought into the project so let’s cd into the react-apollo-client directory and run the npm install for the packages we need for GraphQL and Apollo:

If you would like to familiarize yourself with Apollo and GraphQL, the GraphQL documentation for queries, is an ideal place to start, also see: GraphQL documentation on making queries in Apollo and React.

Building The Master-Detail Page

The airlines.jsx file is where we will be doing most of our work. Let’s start by adding some imports:

Underneath the import { airlineGql } line, we need to import withApolloProvider(), a higher order component.

This will wrap our component with an Apollo Provider, it will give us the ability to use multiple GraphQL endpoints in one project. Maybe, (for instance) I want to also use the GitHub GraphQL API in the same project.

With that in place we need to update the export of my airlines.jsx file.

The line that reads:

export default Airlines

should be changed to:

Our first argument to the HOC is a React Component Airlines (this component). Therefore, when our app is rendered, the <Airlines /> Component will be wrapped with our ApolloProvider. A provider in React is a function of the Context API. Context provides data throughout the component tree in our React application without having to pass data down through props manually.

Our final imports are the two components that I have already built for you (airline-list.jsx and airline-details.jsx):

Once those two files are imported we can add their component syntax to our flexbox grid (simple-flexbox that we have created helping us to easily split our page by a percentage:

With all of this in place, we just need to deal with our data. useQuery returns an object from the Apollo GraphQL client with loading, error, and data properties that we can use. We also need to match on our route’s path (from the URL). Access to that is easy with React Router: (match.params).

Let’s bring React Router’s match in by destructuring the props to the Airlines Component::

Next we will add the following to the top level of our Airlines Component:

What have we just done:

  1. Set airlineId if the match.params.id returns a number and not undefined (do we have an ID in our route path /airlines/1355 or not /airlines/?).
  2. Using the GraphQL query string exported in our airlineGql file. Remember that it returns stuff, so we are destructuring those here as well.
  3. Return “loading” until the data has finished loading
  4. Return “Error” in the case our GraphQL server is not running or has an error, etc…
  5. Capture the data for all of the airlines returned from our query into a local variable named airlines
  6. If match.params.id contains a number it means our route contains an ID, in this case we capture the data for that specific airline into a local variable named airline otherwise we store a null value in that variable.

The match will work because of the way we set up our route in the App.js page:

This route in effect says: Look for a route with the name /airlines/ and anything after it will be available using the match.params.id syntax.

If we run our project right now and our GraphQL Server is not running, we get an error that says: “Error 🙁 Network error: Failed to fetch )” printed out on our page. So we need to go and start that server before we run our React application to test out our master-detail page.

Running Our Full Stack application

To run our fullstack React and GraphQL project, we will need to first add one more package:

Our app is hosted under one domain (localhost:3000), and it tries to make a request to an API on another domain (localhost:4000), the browser’s same-origin policy will block the request.

CORS allows our API to tell the browser that it’s OK for our web app to make requests to it. It does this by sending HTTP headers. We need to use CORS in our Express-GraphQL server. Just add the following code to replace the existing first seven lines.

To get familiar with CORS from the front to the back, check out an article titled: “How to enable CORS for Express-GraphQL & Apollo Server

At this point, we just need to ensure our Couchbase Server instance is up and running.

From the server directory run the node command to start the Express-GraphQL server:

Next, from the client directory lets run the command to start our React client:

The React application connects to the Express-GraphQL API, which in turn queries the Couchbase database to retrieve the Airline data, and now we should have a working app if we visit: localhost:3000

Final preview of  React fullstack application

Using Postinstall and Concurrently

Now that everything’s working, let’s update the project to run both projects with one npm command.

We need to initialize an npm project in our root directory. The server and client both have their own independent node projects. This is fine, it will stay that way, but we are going to give the root directory it’s own package.json file with only one dependency.

Change directories to the root and run:

This will initialize npm and accept all defaults (otherwise remove the -y flag) and install the package we need to concurrently run both projects with one command.

Let’s setup two scripts named client and server to run each project individually and then a start script to run client and server concurrently.

We also will use postinstall to run each project’s npm install script independently when the root’s npm install is complete. postinstall is part of npm scripts by default. All of these changes that we make below will enable someone to clone your repo, run npm install && npm start to which will kick off all three installs and then concurrently run each project.

Replace the package.json that was just added with the following scripts:

We have initialized npm at the root of our project, set up two script for client and server that we can run concurrently with npm start. Also, when someone clone’s our repository, they can now run: npm install && npm start and it will install all packages from the three projects and afterward spin them up, so long as they have Couchbase Server running, it will all just work.

Remove User and Pass From Server File

One final touch is to move the username and password for our Couchbase connection credentials to a .env file. This will ensure we don’t ship sensitive credentials to GitHub for the world to see.

I have purposefully left my credentials in a commit to illustrate another point. If you have a repo that at one point had your credentials in it and then you moved them out, you will still have a commit that exposes those credentials. Be careful, my credentials are fake and I have purposefully done this to show what can happen. All someone would have to do is go back through my commits to find them.

Change directories to couchbase-gql-server/ and install dotenv:

Next, import dotenv and use object destructuring to get access to the variables we have set up in our .env file:

Update the code where we use the username and password:

We will create a file in our server directory named .env and inside that file, we will add our Couchbase Server credentials:

We also need to update the server directories .gitignore file. There is a block of ignores labeled #misc, let’s modify that block of ignores and add .env to it. Remember this file does not get uploaded to git as part of our course control.

Now we just need to run our project from the root using npm start one last time to ensure that everything still works!

Project Recap

We have set up a complete full-stack React and GraphQL project utilizing Couchbase Server and an Apollo GraphQL client and server and we did the entire thing with the knowledge of only JavaScript and JSON, which is amazing to me. I hope this tutorial helped you in your quest to dominate fullstack javaScript, I’m available on Twitter @httpJunkie, feel free to reach out, my DM is always open! Check out the links provided below to get more information on building with Apollo and React.

The final code for this project can be found on GitHub at: github.com/httpJunkie/rage-with-couchbase-final

Apollo and React Resources

Posted by Eric Bishard

International speaker, blogging and advocating for the JavaScript, React, GraphQL and NoSQL community working as a Senior Developer Advocate for Couchbase.

Leave a reply