This is the first of a series of projects to get you familiar with using GraphQL, React and Apollo. In this tutorial I assume the following:
- You have node and npm installed
- You are using Visual Studio Code
- You understand HTML, CSS, and JS
- You have read up on the basics of GraphQL
The last item is very important, you should not only know where the basic documentation for GraphQL is, but you should have skimmed through the following three pages:
If you have not skimmed through these pages, you are not prepared to move forward. At the very least I provide these pages in case you are unsure what a particular line of code is doing in this tutorial.
Project Setup and Dependencies
Create a new directory to house our server and initialize an npm project:
1mkdir gql-server && cd gql-server && npm init -y
Install our dependencies and open our project in Visual Studio Code:
1npm i graphql express express-graphql && code .
We should now have Visual Studio Code open and our project is ready for us to start working in!
Create Our Dummy Data
In a new file named blogs.js
, add an array of objects that we can use for data in our GraphQL server:
1module.exports = [2 {3 id: 1,4 title: 'Preferred Color Scheme in React',5 author: 'Eric Bishard',6 topic: 'React',7 url: 'https://www.reactstateofmind.com/preferred-color-scheme-in-react'8 },9 {10 id: 2,11 title: 'A Guide to Learning React Hooks',12 author: 'Eric Bishard',13 topic: 'Hooks',14 url: 'https://www.reactstateofmind.com/a-guide-to-learning-react-hooks'15 },16 {17 id: 3,18 title: 'React Accessibility Resources',19 author: 'Eric Bishard',20 topic: 'React',21 url: 'https://www.reactstateofmind.com/react-accessibility-resources'22 },23 {24 id: 4,25 title: 'React Developer Advocate',26 author: 'Eric Bishard',27 topic: 'Devrel',28 url: 'https://www.reactstateofmind.com/react-developer-advocate'29 },30 {31 id: 5,32 title: 'Redirect with React Router and Hooks',33 author: 'Eric Bishard',34 topic: 'Hooks',35 url: 'https://www.reactstateofmind.com/redirect-with-react-router-and-hooks'36 },37 {38 id: 6,39 title: 'Writing From a Beginner Developer\'s Perspective',40 author: 'Eric Bishard',41 topic: 'Writing',42 url: 'https://www.reactstateofmind.com/writing-from-a-beginner-developer-s-perspective'43 },44]
Create Our Resolvers
Our GraphQL server will have a few specific endpoints for reading and updating our data.
Given the need to keep things basic I have decided on three endpoints only: blog
, blogs
and updateBlogTopic
.
In a new file named resolvers.js
, add the following functions as module.exports
:
1let blogData = require('./blogs')23module.exports = {4 getBlog: (args) => {5 return blogData.find(blog => blog.id === args.id)6 },7 getBlogs: (args) => {8 return args.topic9 ? blogData.filter(blog => blog.topic === args.topic)10 : blogData11 },12 updateBlogTopic: ({id, topic}) => {13 blogData.map(blog => {14 return blog.id === id15 ? blog.topic = topic16 : blog17 })18 return blogData.find(blog => blog.id === id)19 }20}
In this file we have imported the blog data from our blogs.js
file.
The first resolver getBlog
will allow us to find a specific blog by id
.
The second resolver getBlogs
allows getting all of the blog data if no argument is passed or we can get blogs by topic if an argument for topic
is passed.
The third resolver updateBlogTopic
will set the topic for the blog specified to a new string.
This is not bulletproof code, it’s for demo purposes, but it illustrates how we can serve and manage our data using GraphQL.
Creating the server
In order to create a GraphQL server with a minimal amount of code, we use a package called express-graphql
that enables us to define our schema, a root type, and specify if we want the GraphiQL IDE to be enabled.
In a file named server.js
we will combine the code needed for express
and graphql
to work together.
1const express = require('express')2const graphqlHTTP = require('express-graphql')3const { buildSchema } = require('graphql')45let { getBlog, getBlogs, updateBlogTopic } = require("./resolvers")67const schema = buildSchema(`8 type Query {9 blog(id: Int!): Blog10 blogs(topic: String): [Blog]11 }12 type Mutation {13 updateBlogTopic(id: Int!, topic: String!): Blog14 }15 type Blog {16 id: Int17 title: String18 author: String19 topic: String20 url: String21 }22`)2324const root = {25 blog: getBlog,26 blogs: getBlogs,27 updateBlogTopic: updateBlogTopic28}2930const serverPort = 400031const serverUrl = '/graphql'3233const app = express()34app.use(serverUrl, graphqlHTTP({35 schema: schema,36 rootValue: root,37 graphiql: true38}))3940app.listen(serverPort, () => {41 let message = `GraphQL server now running on http://localhost:${serverPort}${serverUrl}`42 console.log(message)43})
In this file we do the following:
- Import our dependencies (
express
,express-graphql
andgraphql
) - Import our resolvers (which in turn uses our blogs data)
- Define our GraphQL schema, mutations, and types
- Define our root type (Our GraphQL endpoints)
- Create our Express server hosting our GraphQL API
With this final file in place, we are ready to run our project.
Run Our Queries in GraphiQL
In the main project directory (targeting our server.js
file) run:
1node server
This will start our Express/GraphQL server and we can click on the link in the terminal: http://localhost:4000/graphql
Here we will see our GraphiQL IDE, let’s test out each of our endpoints and it’s capabilities!
For each example, we will paste the first code sample into the query pane and if a second code sample exists, it will go into the varaibles pane:
Get a Single Blog
1query getSingleBlog($blogID: Int!) {2 blog(id: $blogID) {3 title4 author5 topic6 url7 }8}
1{"blogID": 1}
Get Blogs by Topic
1query getBlogsByTopic($blogTopic: String!) {2 blogs(topic: $blogTopic) {3 title4 author5 topic6 url7 }8}
1{"blogTopic": "React"}
Get All Blogs
1query {2 blogs {3 title4 author5 topic6 url7 }8}
Get Several Blogs by ID Using Fragments
1query getBlogsWithFragment($blogID1: Int!, $blogID2: Int!) {2 blog1: blog(id: $blogID1) {3 ...blogFields4 }5 blog2: blog(id: $blogID2) {6 ...blogFields7 }8}910fragment blogFields on Blog {11 title12 author13 topic14 url15}
1{2 "blogID1": 1,3 "blogID2": 24}
Mutate/Update Blog Topic by BlogID
1mutation updateBlogTopic($id: Int!, $topic: String!) {2 updateBlogTopic(id: $id, topic: $topic) {3 ...blogFields4 }5}67fragment blogFields on Blog {8 title9 author10 topic11 url12}
1{2 "id": 2,3 "topic": "React Hooks"4}
Summary
We have walked through creating a basic GraphQL server with Node’s Express framework that can handle basic queries and mutations using in-memory data, a list of blogs and learned how to setup resolvers for each endpoint and how to use the GraphiQL IDE to query and test our endpoints and data.
Download the source code on GitHub