{"id":8222,"date":"2020-02-28T16:03:45","date_gmt":"2020-02-29T00:03:45","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=8222"},"modified":"2025-06-13T21:03:55","modified_gmt":"2025-06-14T04:03:55","slug":"fullstack-react-apollo-3","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/","title":{"rendered":"Fullstack React and GraphQL : Apollo Client"},"content":{"rendered":"<p>The third of three articles focused on building Fullstack React and GraphQL with the Apollo GraphQL Client.<\/p>\n<ul>\n<li><a href=\"https:\/\/www.couchbase.com\/blog\/fullstack-react-couchbase-1\/\">Setting up a NoSQL Couchbase Server (Part 1)<\/a><\/li>\n<li><a href=\"https:\/\/www.couchbase.com\/blog\/fullstack-react-express-2\/\">Building an Express-GraphQL API (Part 2)<\/a><\/li>\n<li>Create Apollo GraphQL Client in React (Part 3)<\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/rage-with-couchbase-final\">Final Source Code<\/a><\/li>\n<\/ul>\n<h2 id=\"creating-the-react-app\">Creating the React Application with an Apollo GraphQL client<\/h2>\n<p>In this segment of the tutorial, I will help you plug in the parts related to using Apollo GraphQL. I&#8217;ve included most of the React app that you will need in a GitHub 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.<\/p>\n<h3 id=\"clone-existing-react-app\">Clone an Existing React Application<\/h3>\n<p>Our decoupled React frontend will be a sibling to the <code>couchbase-gql-server<\/code> directory. here is a basic idea of what our directory structure will look like:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false striped:false nums:false lang:sh decode:true\" title=\"Directory Structure\">  \r\n  rage-with-couchbase\r\n  \u2502   \r\n  \u2514\u2500\u2500\u2500couchbase-gql-server\r\n  \u2502   \r\n  \u2514\u2500\u2500\u2500react-apollo-client\r\n<\/pre>\n<p>Let&#8217;s clone the starting point for our React project by running the following git command from the root (<code>rage-with-couchbase<\/code> directory) in our terminal:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Clone Repo and Remove Git Details\">git clone https:\/\/github.com\/httpJunkie\/react-apollo-client.git &amp;&amp; cd react-apollo-client &amp;&amp; rm -rf .git<\/pre>\n<p>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&#8217;s encouraged so that you don&#8217;t lose your work.<\/p>\n<p>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&#8217;s run the React application on its own just to make sure everything is working with no errors:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"NPM Install and Start\">npm install &amp;&amp; npm start<\/pre>\n<p><a href=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/02\/react-starting-point-layout.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-8230\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/02\/react-starting-point-layout.jpg\" alt=\"preview of our React starting point\" width=\"1020\" height=\"713\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/react-starting-point-layout.jpg 1020w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/react-starting-point-layout-300x210.jpg 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/react-starting-point-layout-768x537.jpg 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/react-starting-point-layout-20x14.jpg 20w\" sizes=\"auto, (max-width: 1020px) 100vw, 1020px\" \/><\/a><\/p>\n<p>Open the console (<strong>\u2318 Cmd + \u2325 Option + I<\/strong> on Mac) (<strong>Ctrl + \u2191 Shift + J<\/strong> on PC)<\/p>\n<p>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&#8217;s like someone else already took care of all the styling and basic layout, our job will be to hook up the <code>airline-list.jsx<\/code> and <code>airline-details.jsx<\/code> 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!<\/p>\n<p>Before we make changes to the React app, let&#8217;s understand some of the files that we have in our project that are not yet in play with our Airline route.<\/p>\n<h3 id=\"overview-of-assets\">Overview of Our Assets<\/h3>\n<p>There are 6 files we want to make ourselves familiar with that are standing by and awaiting our use.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/hoc\/withApolloProvider.js\">hoc\/withApolloProvider.js<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-list.jsx\">partial\/airline-list.jsx<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-details.jsx\">partial\/airline-details.jsx<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/utility\/pagination.jsx\">utility\/pagination.jsx<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/utility\/pagination.scss\">utility\/pagination.scss<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/routes\/airline-gql.js\">routes\/airline-gql.js<\/a><\/li>\n<\/ul>\n<p>A convention that we are using regarding directory structure is that components in the &#8220;<code>routes<\/code>&#8221; directory are React components that are resolved to form a specific route and those files inside of the &#8220;<code>partial<\/code>&#8221; 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.<\/p>\n<p><strong>withApolloProvider<\/strong> &#8211; I am using a higher-order component for readability. Just understand that this is similar to importing the ApolloProvider into a parent component. This may not be best practice, but I like that it keeps my code tidy.<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:default decode:true \" title=\"WithApolloProvider Higher Order Component\">import React from 'react'\r\nimport { ApolloProvider, InMemoryCache, ApolloClient } from '@apollo\/client';\r\n\r\nconst withApolloProvider = (WrappedComponent, graphqlEndpoint) =&gt; {\r\n  const apolloClient = new ApolloClient({\r\n    uri: graphqlEndpoint,\r\n    cache: new InMemoryCache()\r\n  })\r\n\r\n  return (props) =&gt; (\r\n    &lt;ApolloProvider client={apolloClient}&gt;\r\n      &lt;WrappedComponent {...props} wrappedBy={\"withApolloProvider\"} \/&gt;\r\n    &lt;\/ApolloProvider&gt;\r\n  )\r\n}\r\n\r\nexport default withApolloProvider<\/pre>\n<p>We have <a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-list.jsx\"><code>airline-list.jsx<\/code><\/a> and a <a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-details.jsx\"><code>airline-details.jsx<\/code><\/a>, these two components will get loaded side by side in our <code>airlines.jsx<\/code> component. The list will simply display each airline and uses <a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/utility\/pagination.jsx\"><code>pagination.jsx<\/code><\/a> to ensure we don&#8217;t have a long list running down the left side of the page.<\/p>\n<p>Finally, we have the <code>airline-gql.js<\/code> file which is simply our <a href=\"https:\/\/www.couchbase.com\/blog\/processing-graphql-queries-with-java-spring-boot-and-nosql\/\">GraphQL query<\/a> for all UK Airlines. I like to separate my queries out into another file for organizational purposes, it&#8217;s not required, but it cleans up the <code>airlines.jsx<\/code> file.<\/p>\n<h3 id=\"how-our-master-detail-page-works\">How Our Master-Detail Page Works<\/h3>\n<p>In our project, we have a master-detail component relationship (<code>airline-list.jsx<\/code> &amp;&amp; <code>airline-details.jsx<\/code>), at the <code>\/airlines<\/code> route. This route resolves to a view component named: <code>airlines.jsx<\/code>, which utilizes React Router&#8217;s capabilities to match not only the route but an additional URI parameter (<code>airlineId<\/code>) which we can append to the end of the route to be specific. When no specific <code>airlineId<\/code> URI parameter is present in the URL:<\/p>\n<p><code>https:\/\/localhost:3000\/airlines<\/code><\/p>\n<p>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: <strong>&#8220;Select an airline&#8221;<\/strong>.<\/p>\n<p>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 &lt;Link \/&gt; component provided by React Router:<\/p>\n<p><code>https:\/\/localhost:3000\/airlines\/1355<\/code><\/p>\n<p>Here we will match the ID <code>1355<\/code> with the correct airline already in memory in our React application data and display its appropriate Airline information &#8220;British Airways&#8221;.<\/p>\n<h3 id=\"adding-dependencies-for-our-apollo-graphql-client\">Adding Dependencies for our Apollo GraphQL client<\/h3>\n<p>We need three packages: <a href=\"https:\/\/www.npmjs.com\/package\/@apollo\/react-hooks\"><code>@apollo\/react-hooks<\/code><\/a>, <a href=\"https:\/\/www.npmjs.com\/package\/apollo-boost\"><code>apollo-boost<\/code><\/a>, and <a href=\"https:\/\/www.npmjs.com\/package\/graphql\"><code>graphql<\/code><\/a>, brought into the project so let&#8217;s <code>cd<\/code> into the <code>react-apollo-client<\/code> directory and run the <code> npm install <\/code> for the packages we need for GraphQL and Apollo:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Install Apollo Client 3 and GraphQL\">npm install @apollo\/client graphql<\/pre>\n<p>If you would like to familiarize yourself with Apollo and GraphQL, the <a href=\"https:\/\/www.apollographql.com\/docs\/react\/data\/queries\/\">GraphQL documentation for queries<\/a>, is an ideal place to start, also see: <a href=\"https:\/\/www.apollographql.com\/docs\/react\/data\/queries\/#executing-a-query\">GraphQL documentation on making queries<\/a> in Apollo and React.<\/p>\n<h3 id=\"building-the-master-detail-page\">Building The Master-Detail Page<\/h3>\n<p>The `airlines.jsx` file is where we will be doing most of our work. Let&#8217;s start by adding some imports:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:javascript decode:true\" title=\"Imports for Airlines Component\">import { useQuery } from '@apollo\/client'\r\nimport { airlineGql } from '.\/airline-gql'<\/pre>\n<p>Underneath the `import { airlineGql }` line, we need to import <code>withApolloProvider<\/code>, a higher-order component.<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:javascript decode:true\" title=\"Import Apollo Provider HOC\">import withApolloProvider from '..\/hoc\/withApolloProvider'<\/pre>\n<p>This wraps our component with an Apollo Provider. I have used this method instead of wrapping our entire application with an ApollloProvider. An attempt to make the code I am sharing a little less complex. We will update the <code>airlines.jsx<\/code> file&#8217;s export.<\/p>\n<p>The line that reads:<\/p>\n<p><strong><code>export default Airlines<\/code><\/strong><\/p>\n<p>should be changed to:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:javascript decode:true\" title=\"Update Airlines Component's Export with Wrapped Component\">const WrappedComponent = withApolloProvider(Airlines, 'https:\/\/localhost:4000\/graphql')\r\nexport default WrappedComponent<\/pre>\n<p>Our first argument to the HOC is a React Component `Airlines` (this component). Therefore, when our app is rendered, the <code>&lt;Airlines \/&gt;<\/code> component will be wrapped with our <a href=\"https:\/\/www.apollographql.com\/docs\/react\/get-started\/#connect-your-client-to-react\">ApolloProvider<\/a>. 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. In our case, the <code>&lt;Airlines \/&gt;<\/code> component will be wrapped with our provider giving it access to the data provided by the Apollo Client code defined in that <code>withApolloProvider<\/code> higher-order component.<\/p>\n<p>Our final imports are the two components that I have already built for you (<a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-list.jsx\">airline-list.jsx<\/a> and <a href=\"https:\/\/github.com\/httpJunkie\/react-apollo-client\/blob\/master\/src\/components\/partial\/airline-details.jsx\">airline-details.jsx<\/a>):<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:javascript decode:true\" title=\"Import AirlineList &amp; AirlineDetails Components\">import AirlineList from '..\/partial\/airline-list'\r\nimport AirlineDetails from '..\/partial\/airline-details'<\/pre>\n<p>Once those two files are imported we can add their component syntax to our flexbox grid (<a href=\"https:\/\/www.npmjs.com\/package\/simple-flexbox\">simple-flexbox<\/a> that we have created helping us to easily split our page by a percentage:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:jsx decode:true\" title=\"Flexbox Split Screen\">&lt;Row horizontal=\"spaced\"&gt;\r\n  &lt;Column flexGrow={1} style={{ minWidth: '280px', width: '65%' }}&gt;\r\n    &lt;AirlineList airlines={airlines} \/&gt;\r\n  &lt;\/Column&gt;\r\n  &lt;Column flexGrow={1} style={{ width: '45%' }}&gt;\r\n    &lt;AirlineDetails airline={airline} \/&gt;\r\n  &lt;\/Column&gt;\r\n&lt;\/Row&gt;<\/pre>\n<p>With all of this in place, we just need to deal with our data. <code>useQuery<\/code> returns an object from the Apollo GraphQL client with <code>loading<\/code>, <code>error<\/code>, and <code>data<\/code> properties that we can use. We also need to match on our route&#8217;s path (from the URL). Access to that is easy with React Router: (<code>match.params<\/code>).<\/p>\n<p>Let&#8217;s bring React Router&#8217;s `match` in by destructuring the props to the `Airlines` Component::<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:javascript decode:true\" title=\"Destrucure match from React Router Provider Data\">const Airlines = ({ match }) =&gt; {<\/pre>\n<p>Next, we will add the following to the top level of our <code>Airlines<\/code> Component:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:javascript decode:true\" title=\"Load Airline Data and Match Selected Airline\">const airlineId = Number(match.params.id)\r\n  const { loading, error, data } = useQuery(airlineGql)\r\n\r\n  if (loading) return &lt;p&gt;Loading...&lt;\/p&gt;\r\n  if (error) return &lt;p&gt;Error :( &lt;span style={{color: 'red'}}&gt;{error.message}&lt;\/span&gt; )&lt;\/p&gt;\r\n\r\n  const airlines = data.airlinesUK\r\n  const airline = match.params.id ? airlines.find(a =&gt; a.id === airlineId) : null<\/pre>\n<p><strong>What have we just done:<\/strong><\/p>\n<ol>\n<li>Set <code>airlineId<\/code> if the <code>match.params.id<\/code> returns a number and not <code>undefined<\/code> (do we have an ID in our route path <code>\/airlines\/1355<\/code> or not <code>\/airlines\/<\/code>?).<\/li>\n<li>Using the GraphQL query string exported in our <code>airlineGql<\/code> file. Remember that it returns stuff, so we are destructuring those here as well.<\/li>\n<li>Return &#8220;loading&#8221; until the data has finished loading<\/li>\n<li>Return &#8220;Error&#8221; in the case our GraphQL server is not running or has an error, etc&#8230;<\/li>\n<li>Capture the data for all of the airlines returned from our query into a local variable named <code>airlines<\/code><\/li>\n<li>If <code>match.params.id<\/code> 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 <code>airline<\/code> otherwise we store a null value in that variable.<\/li>\n<\/ol>\n<p>The <code>match<\/code> will work because of the way we set up our route in the <code>App.js<\/code> page:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:jsx decode:true\" title=\"Update React Router Definition\">&lt;Route exact path={[\"\/airlines\/:id\", \"\/airlines\/\"]}\r\n  render={(props) =&gt; &lt;Airlines {...props} \/&gt;}\r\n\/&gt;<\/pre>\n<p>This route in effect says: Look for a route with the name <code>\/airlines\/<\/code> and anything after it will be available using the <code>match.params.id<\/code> syntax.<\/p>\n<p>If we run our project right now and our GraphQL Server is not running, we get an error.<br \/>\n&#8220;Error :( Network error: Failed to fetch )&#8221;<\/p>\n<p>So we need to start that server before we run our React app to test our master-detail page.<\/p>\n<h3 id=\"running-our-app\">Running Our Full Stack application<\/h3>\n<p>To run our fullstack React and GraphQL project, we will need to first add one more package:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Install CORS Package\">npm install cors<\/pre>\n<p>Our app is hosted under one domain (localhost:3000). It makes requests to an API on another domain (localhost:4000). Without CORS the browser&#8217;s same-origin policy will block the request.<\/p>\n<p>CORS allows our API to tell the browser that it&#8217;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.<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:javascript decode:true\" title=\"Add CORS Support to the Express Application\">const express = require('express')\r\nconst cors = require('cors')\r\nconst graphqlHTTP = require('express-graphql')\r\nconst { buildSchema } = require('graphql')\r\n  \r\nconst couchbase = require('couchbase')\r\n  \r\nconst app = express()\r\napp.use(cors())<\/pre>\n<p>To get familiar with CORS from the front to the back, check out an article titled: &#8220;<a href=\"https:\/\/www.prisma.io\/blog\/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d\">How to enable CORS for Express-GraphQL &amp; Apollo Server<\/a>&#8221;<\/p>\n<p>At this point, we just need to ensure our Couchbase Server instance is up and running.<\/p>\n<p>From the server directory run the node command to start the Express-GraphQL server:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:jsx decode:true\" title=\"Run Server\">node server<\/pre>\n<p>Next, from the client directory lets run the command to start our React client:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Start Express Server\">npm start<\/pre>\n<p>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: <a href=\"https:\/\/localhost:3000\/\">localhost:3000<\/a><\/p>\n<p><a href=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/02\/final-project.gif\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-8232\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/02\/final-project.gif\" alt=\"Final preview of React fullstack application\" width=\"1022\" height=\"840\" \/><\/a><\/p>\n<h2 id=\"using-postinstall-and-concurrently\">Using Postinstall and Concurrently<\/h2>\n<p>Now that everything&#8217;s working, let&#8217;s update the project to run both projects with one npm command.<\/p>\n<p>We need to initialize an npm project in our root directory. The server and client both have their own project directories. We give the root directory its own `package.json` file with only one dependency.<\/p>\n<p>Change directories to the root and run:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Initialize Root as NPM Project and Install Concurrently\">npm init -y &amp;&amp; npm install concurrently --save-dev<\/pre>\n<p>This will initialize npm and accept all defaults (otherwise remove the <code>-y<\/code> flag) and install the package we need to concurrently run both projects with one command.<\/p>\n<p>Let&#8217;s set up two scripts named <code>client<\/code> and <code>server<\/code> to run each project individually and then a <code>start<\/code> script to run client and server concurrently.<\/p>\n<p>We also will use <code>postinstall<\/code> to run each project&#8217;s <code>npm install<\/code> script independently when the root&#8217;s <code>npm install<\/code> is complete. <code>postinstall<\/code> is part of <a href=\"https:\/\/docs.npmjs.com\/misc\/scripts\">npm scripts<\/a> by default. All of these changes that we make below will enable someone to clone your repo, run `npm install &amp;&amp; npm start` to which will kick off all three installs, and then concurrently run each project.<\/p>\n<p>Replace the <code>package.json<\/code> that was just added with the following scripts:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false lang:sh decode:true\" title=\"Package.json Scripts\">\"scripts\": {\r\n    \"client\": \"cd react-apollo-client &amp;&amp; npm start\",\r\n    \"server\": \"cd couchbase-gql-server &amp;&amp; node server\",\r\n    \"start\": \"concurrently --kill-others \\\"npm run server\\\" \\\"npm run client\\\"\",\r\n    \"postinstall\": \"(cd couchbase-gql-server &amp;&amp; npm install); (cd react-apollo-client &amp;&amp; npm install);\"\r\n  },<\/pre>\n<p>We have initialized npm at the root of our project, set up two scripts for <code>client<\/code> and <code>server<\/code> that we can run concurrently with <code>npm start<\/code>. Also, when someone clone&#8217;s our repository, they can now run: <code>npm install &amp;&amp; npm start<\/code> 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.<\/p>\n<h2 id=\"remove-user-and-pass-from-server-file\">Remove User and Pass From Server File<\/h2>\n<p>One final touch is to move the username and password for our Couchbase connection credentials to a <code>.env<\/code> file. This will ensure we don&#8217;t ship sensitive credentials to GitHub for the world to see.<\/p>\n<p>Change directories to <code>couchbase-gql-server\/<\/code> and install <code>dotenv<\/code>:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Install CORS Package\">npm install dotenv --save-dev<\/pre>\n<p>Next, import <code>dotenv<\/code> and use object destructuring to get access to the variables we have set up in our <code>.env<\/code> file:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:javascript decode:true\" title=\"Require .env User and Pass\">require('dotenv').config()\r\nconst { cbUser, cbPass } = process.env<\/pre>\n<p>Update the code where we use the username and password:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:javascript decode:true\" title=\"Update Credentials in Couchbase Connection\">const cluster = new couchbase.Cluster('couchbase:\/\/localhost', { \r\n  username: cbUser, password: cbPass \r\n})<\/pre>\n<p>Create a file in our <code>couchbase-gql-server<\/code> directory named <code>.env<\/code>\u00a0 with our Couchbase Server credentials:<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Store Server Credentials\">cbUser=Administrator\r\ncbPass=password<\/pre>\n<p>We also need to update the server directories `.gitignore` file. There is a block of ignores labeled `#misc`, let&#8217;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.<\/p>\n<pre class=\"theme:vs2012 font:ubuntu-mono font-size:14 line-height:24 top-margin:0 h-align:1 toolbar:1 toolbar-overlay:false nums:false lang:sh decode:true\" title=\"Git Ignore\"># misc\r\n.DS_Store\r\n.env\r\n.env.local\r\n.env.development.local\r\n.env.test.local\r\n.env.production.local<\/pre>\n<p>Let&#8217;s run our project from the root using `npm start` to ensure that everything still works!<\/p>\n<h2 id=\"project-recap\">Project Recap<\/h2>\n<p>We have set up a fullstack React and GraphQL project. Utilizing <a href=\"https:\/\/docs.couchbase.com\/nodejs-sdk\/current\/hello-world\/start-using-sdk.html\">Couchbase Node SDK<\/a> and Apollo GraphQL client &amp; server, we leverage our knowledge of JavaScript to build a fullstack app. I hope this tutorial helps in your quest to dominate fullstack JavaScript.<\/p>\n<p>I&#8217;m available on Twitter <a href=\"https:\/\/www.twitter.com\/httpJunkie\">@httpJunkie<\/a>, 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.<\/p>\n<p>The final code for this project can be found on GitHub at:<br \/>\n<a href=\"https:\/\/github.com\/httpJunkie\/rage-with-couchbase-final\">github.com\/httpJunkie\/rage-with-couchbase-final<\/a><\/p>\n<h2>Apollo and React Resources<\/h2>\n<ul>\n<li><a href=\"https:\/\/www.apollographql.com\/\">Apollo GraphQL<\/a><\/li>\n<li><a href=\"https:\/\/www.apollographql.com\/docs\/\">Apollo GraphQL Documentation<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=Ct2-5dUfMMw\">The Benefits of Apollo GraphQL<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/apollographql\/react-apollo\">React Apollo on GitHub<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=RCKkWjBuyfw\">Apollo Client With React on LevelUp Tuts<\/a><\/li>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=9Qw8HKatjy8\">Apollo + GraphQL + React \u2014 Thinking in Queries with James Baxley<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The third of three articles focused on building Fullstack React and GraphQL with the Apollo GraphQL Client. Setting up a NoSQL Couchbase Server (Part 1) Building an Express-GraphQL API (Part 2) Create Apollo GraphQL Client in React (Part 3) Final [&hellip;]<\/p>\n","protected":false},"author":53002,"featured_media":10876,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,1822,1812,2201],"tags":[2210,2454],"ppma_author":[8922],"class_list":["post-8222","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-node-js","category-n1ql-query","category-tools-sdks","tag-graphql","tag-react"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Fullstack React and GraphQL : Apollo Client - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Fullstack React and GraphQL : Apollo Client\" \/>\n<meta property=\"og:description\" content=\"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-02-29T00:03:45+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:03:55+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Eric Bishard\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@httpJunkie\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eric Bishard\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\"},\"author\":{\"name\":\"Eric Bishard\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/67d3a4b597e42370ccd34b715a6b1f4c\"},\"headline\":\"Fullstack React and GraphQL : Apollo Client\",\"datePublished\":\"2020-02-29T00:03:45+00:00\",\"dateModified\":\"2025-06-14T04:03:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\"},\"wordCount\":2159,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg\",\"keywords\":[\"graphql\",\"React\"],\"articleSection\":[\"Couchbase Server\",\"Node.js\",\"SQL++ \/ N1QL Query\",\"Tools &amp; SDKs\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\",\"name\":\"Fullstack React and GraphQL : Apollo Client - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg\",\"datePublished\":\"2020-02-29T00:03:45+00:00\",\"dateModified\":\"2025-06-14T04:03:55+00:00\",\"description\":\"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg\",\"width\":1200,\"height\":628,\"caption\":\"RAGE With Couchbase Apollo-GraphQL Featured Image\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fullstack React and GraphQL : Apollo Client\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/67d3a4b597e42370ccd34b715a6b1f4c\",\"name\":\"Eric Bishard\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/b7d1d2580c41d35a21654fb1abe65d23\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/a316a2658772914defd259571b8cad18878eb23c9d0cc3a97dd803deca0c09ca?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/a316a2658772914defd259571b8cad18878eb23c9d0cc3a97dd803deca0c09ca?s=96&d=mm&r=g\",\"caption\":\"Eric Bishard\"},\"description\":\"International speaker, blogging and advocating for the JavaScript, React, GraphQL and NoSQL community working as a Senior Developer Advocate for Couchbase.\",\"sameAs\":[\"https:\/\/www.reactstateofmind.com\",\"https:\/\/www.linkedin.com\/in\/eric-b\/\",\"https:\/\/x.com\/httpJunkie\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/eric-bishard\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Fullstack React and GraphQL : Apollo Client - The Couchbase Blog","description":"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/","og_locale":"en_US","og_type":"article","og_title":"Fullstack React and GraphQL : Apollo Client","og_description":"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.","og_url":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/","og_site_name":"The Couchbase Blog","article_published_time":"2020-02-29T00:03:45+00:00","article_modified_time":"2025-06-14T04:03:55+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg","type":"image\/jpeg"}],"author":"Eric Bishard","twitter_card":"summary_large_image","twitter_creator":"@httpJunkie","twitter_misc":{"Written by":"Eric Bishard","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/"},"author":{"name":"Eric Bishard","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/67d3a4b597e42370ccd34b715a6b1f4c"},"headline":"Fullstack React and GraphQL : Apollo Client","datePublished":"2020-02-29T00:03:45+00:00","dateModified":"2025-06-14T04:03:55+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/"},"wordCount":2159,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg","keywords":["graphql","React"],"articleSection":["Couchbase Server","Node.js","SQL++ \/ N1QL Query","Tools &amp; SDKs"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/","url":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/","name":"Fullstack React and GraphQL : Apollo Client - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg","datePublished":"2020-02-29T00:03:45+00:00","dateModified":"2025-06-14T04:03:55+00:00","description":"Create an Apollo GraphQL client for fetching data in our three part series on fullstack applications using React, Apollo, GraphQL and Express.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/02\/apollo-graphql-1.jpg","width":1200,"height":628,"caption":"RAGE With Couchbase Apollo-GraphQL Featured Image"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/fullstack-react-apollo-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Fullstack React and GraphQL : Apollo Client"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/67d3a4b597e42370ccd34b715a6b1f4c","name":"Eric Bishard","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/b7d1d2580c41d35a21654fb1abe65d23","url":"https:\/\/secure.gravatar.com\/avatar\/a316a2658772914defd259571b8cad18878eb23c9d0cc3a97dd803deca0c09ca?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/a316a2658772914defd259571b8cad18878eb23c9d0cc3a97dd803deca0c09ca?s=96&d=mm&r=g","caption":"Eric Bishard"},"description":"International speaker, blogging and advocating for the JavaScript, React, GraphQL and NoSQL community working as a Senior Developer Advocate for Couchbase.","sameAs":["https:\/\/www.reactstateofmind.com","https:\/\/www.linkedin.com\/in\/eric-b\/","https:\/\/x.com\/httpJunkie"],"url":"https:\/\/www.couchbase.com\/blog\/author\/eric-bishard\/"}]}},"authors":[{"term_id":8922,"user_id":53002,"is_guest":0,"slug":"eric-bishard","display_name":"Eric Bishard","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/a316a2658772914defd259571b8cad18878eb23c9d0cc3a97dd803deca0c09ca?s=96&d=mm&r=g","author_category":"","last_name":"Bishard","first_name":"Eric","job_title":"","user_url":"https:\/\/www.reactstateofmind.com","description":"International speaker, blogging and advocating for the JavaScript, React, GraphQL and NoSQL community working as a Senior Developer Advocate for Couchbase."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/8222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/53002"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=8222"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/8222\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/10876"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=8222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=8222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=8222"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=8222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}