Consume a GraphQL API from a React Application
React is a JavaScript library used to create websites, it allows us to create Single Page Applications. The server will only send a single HTML page to the browser for the website to run fully, the react application manages the whole website including the data, user interaction, and routing.
Although React is a library rather than a language, it is widely used in web development. The library first appeared in May 2013 and is now one of the most commonly used frontend libraries for web development.
We will create a simple project that will teach us the fundamentals of React which include:
- Keeping and tracking application state
- Using a router to display pages/components
- Fetching application data for the UI
Before following along I suggest that you at least know HTML & CSS, GraphQL, and JavaScript. We will use these technologies to simplify local development of a react application that uses a fake GraphQL API as its backend. The solution to be built is a Blog that lets us manage content.
Creating a React Application
The easiest way to initialize a react application is to use the CLI, you’ll need to have Node >= 14.0.0 and npm >= 5.6 on your machine. The tool will generate a starter react project which has all required configuration that's needed to compile the code to a production ready application.
Step 1: Initialize a React application
Navigate to the directory that you want to create the project and run the below commands:
Once you open the starter project folder in your chosen IDE (i.e. Visual Studio Code), you will see all the files that were auto generated by create-react-app
. Lets do a brief overview of the folders and files:
- All of the project's dependencies live in the
node_modules
folder, including the react library as well. Any other packages we need to install later on, will also be stored inside this folder. - Any files that are accessible by the browser are stored in the
public
folder. The index.html is stored here as well and will be served to the browser and all of the react application code will be injected by this file. - The application code will be stored in the
src
folder, this includes all components written in react. There's an app.js file that's already created and this is what a component looks like. - The index.js file takes all of the react components and mounts them to the DOM.
- The package.json file lists all dependencies required to run the application and also provides scripts to perform certain actions for our project.
Step 2: Code refactor and Adding Components
The generated application has a default root component called App.js, it's the first component that gets rendered in the DOM. We will modify the component and add our custom styling:
If we need more components (Navbar, PostDetail, SideBar) for our application, they will be nested in the App.js component. Let's create a Navbar.js component inside the src
folder. This component will be placed at the top of the DOM:
We need a Home component that will store thee home page content, it's possible to just place this content in the root component but that doesn't follow best practice. Lets create a Home.js component inside the src
folder for the content of our home page:
This is how we create multiple components and import/nest them into other components.
Step 3: Address styling for the application
So we have our three different components (App, Navbar, and Home), we will now add some CSS to all these components. If you look closely to all the components we have created, we added the className
in each file. We will use the index.css to style the application:
We should see the styles applied to our application when we visit http://localhost:3000/ on the browser.
Step 4: Using Sate (useState hook)
Let's create a state to represent the blog posts, and to achieve we will use the useSate hook provided by react. The data for the posts might change overtime, so react will update the DOM when this happens.
The sate of a component refers to the data being used in the component, at that point in time. The state can be an array of values, booleans, strings, objects, or any data that a component uses.
Since we are building a simple blog, ideally we need to have a list of posts to output in a template. Inside the Home.js component we will display all the posts available, we will use dummy data for now:
Now if everything is saved and the application is running, we should see the following on the browser:
Creating a Fake GraphQL API
In the previous steps, we hardcoded our blog posts data. This is not ideal for web applications as we need our data coming from a database using an API endpoint. I will not deep-dive into creating a database and an API from scratch, feel free to checkout Generate a GraphQL API from a DynamoDB Table post.
Step 1: Using json-graphql-server
It is possible to create a full GraphQL API just using a javascript file that will store our data. The db.js file will act as our database, let's create this file in the root directory of our application:
To start using the GraphQL API issue the commands below in the root directory of your application:
npm i json-graphql-server
json-graphql-server db.js --p 3001
The json-graphql-server package gives us a full GraphQL API, so we get both queries and mutations for the entities in the database file.
To use a port other than 3001 or host other than localhost, you can run:
-
json-graphql-server db.js --p <your port here>
-
json-graphql-server db.js --h <your host here>
To test the API, go to http://localhost:3001/?query={ allPosts { title body Author { name } } }.
Step 2: Get started with Apollo Client
If you want to build apps with React and GraphQL, Apollo is the library you should use. Apollo is the glue that binds these two tools together. Plus it makes working with React and GraphQL a lot easier by giving us a lot of custom React hooks and features that enable us to both write GraphQL operations and execute them with JavaScript code.
Apollo is a library that brings together two incredibly useful technologies used to build web and mobile apps: React and GraphQL.
Let's install the packages we need and initialize the Apollo Client:
- The
@apollo/client
package contains virtually everything you need to set up Apollo Client. It includes the in-memory cache, local state management, error handling, and a React-based view layer. - The
graphql
package provides logic for parsing GraphQL queries.
Now that we have the dependencies we need, let's configure an ApolloClient
instance inside the index.js file:
Let's go over the code configuration above:
- Import the symbols we need from
@apollo/client
to setup the GraphQL API. - Initialize
ApolloClient
with uri (URL of our GraphQL server ) and cache (cache query results after fetching them) fields. ApolloProvider
wraps the React app and places Apollo Client on the context, which enables you to access it from anywhere in your component tree.
After your ApolloProvider
is hooked up, you can start requesting data with useQuery
which is a React hook that shares GraphQL data with your UI.
Step 3: Fetch data using the GraphQL API
We initially hardcoded application data in the Home.js component. Now we will modify this and allow our component to execute the POSTS_QUERY
with the useQuery
hook. Let's first define the query by wrapping it in the gql
template literal:
Whenever this component renders, the useQuery
hook automatically executes our query and returns a result object containing loading
, error
, and data
properties:
- Apollo Client tracks a query's error and loading state for you, which are reflected in the
loading
anderror
properties. - When the result of your query comes back, it's attached to the
data
property.
Step 4: Add data using the GraphQL API
Now we can focus on adding data to our database, in order to do this we need to look at controlled inputs (forms). Forms lets us track input values from the user, you can have a look at the Create.js component in my GitHub consume-graphql-api repo.
The useMutation
React hook is the primary API for executing mutations in an Apollo application.
First, we'll create a corresponding GraphQL ADD_POST
mutation. Remember to wrap GraphQL strings in the gql
function to parse them into query documents:
We will capture the blogs' post data using this form:
To execute a mutation, you first call useMutation
within a React component and pass it the mutation you want to execute, like so:
In this Create.js component, our form's onSubmit
handler calls the mutate function (named addPost
) that's returned by the useMutation
hook. This tells Apollo Client to execute the mutation by sending it to our GraphQL server.
Feel free to test the API on http://localhost:3001/?query=mutation { createPost(title%3A "Mutate Function"%2C body%3A "Add data using the GraphQL API"%2C author_id%3A 1) { Author { name } } }.
Summary
This was just scratching the surface on how to consume a GraphQL API from a React Application. The was so much we did, so checkout consume-graphql-api repo on my GitHub if you come across any issues.