Here we want to create a simple CRUD app with react, GraphQL, Node.js and MongoDB- part 1, let's go:
You can find source code here: source code
Project Overview
This project has two folders, server and client. In this post we just work on the server(Backend) and for the next post we will work on the client(Frontend).
Backend:
We make a GraphQL server on node.js by using Express. This is where we describe how our Graph looks like, different types of data on our Graph, relationship between these data types, setting up different entry points (where we can query and retrieve information) to our Graph. And then we use MongoDB to store our data.
Frontend:
For the client side we use React, and also we use
Apollo, it allows us to use GraphQL on the frontend and inside react.
Also, we have GraphiQL it is like a frontend application that allows us to make a request to GraphQL and retrieve data back.
Start working on project
1. Initialize a node project : npm init
Inside the project folder, run this command, and it is going to create a package.json file for us.
2. Inside project folder we should create a folder and call it to server, all of our server side code will be inside this folder.
3. Create an express application: npm install express
4. Create index.js file
Inside this file we:
- Set up our
express appand listen to a specific port(5000). - Set up our
GraphQL.we need to install two package:npm install graphql express-graphql.first one is the maingraphqlpackage which is aJavaScriptimplantation ofGraphQL, the second one is a package that help our express app to interact withGraphQLbecauseexpressdoesn't understandGraphQL(requireexpress-graphqlmodule(grapqlHTTP)). - Setup some middleware. The way that we do that in express is by using app.use(). Like this one :
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true
}));
Here we say the route that we gonna use on this middleware is /graphql and then fire a function. when a request to/graphql comes in and this function going to handle our GraphQL requests, and it takes some options inside an object. We have to pass schema and graphiql: true as a property to this middleware.
Schema, going to tell express graphql about our data and how graph will looks like.it says what data types are in the graph and relationship between them.
5. Create Schema.js file
schema has three responsibility:
define Object Type, define relationship between Object Type, define rootQuery.
Create a
Schemato describe how the data in our graph will looks like, inside this file we're going to define our schema.
Schemadescribe theobject typeand the relations between theseobject types, how we can read data and interact with them.Require the
GraphQL. We install this package before.We define
ObjectTypeand define what thisObjectTypeis about (define name & fields)
Here, we just define one object type:TodoType.
const TodoType = new GraphQLObjectType({
name: 'Todo',
fields: () => ({
id: { type: GraphQLID },
title: { type: GraphQLString }
})
});
The GraphQLObjectType is a function and takes in an object and this object going to define what this TodoType is all about.
name: a name for our object type.
fields:it is a function that returns an object, it's define the fields on this TodoType and then say what type is our fields.
6. Create RootQuery
RootQeury:it is our entry point to the graph. How we describe, a user can initially jump to the graph and grab data.We define
fieldsof thisRoot Queryand each of this fields going to be a type ofRootQuery.first one is going to be a query for list oftodosand the second is for onetodoand the argument that we expected to get along with this query isid.Also, we have type and resolve function for each field.
resolvefunction : how to get data when someone requested.it is for grabbing data and return what is needed.
this resolve function takes two parameters :parent&args.parentcoming to play when we start relationship between data.
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
todos: {
type: new GraphQLList(TodoType),
resolve(parent, args) {
return Todo.find();
}
},
todo: {
type: TodoType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Todo.findById(args.id);
}
}
})
});
7. Connect to database
To connect to the database, create a folder called config and then create db.js file inside it: server/config/db.js.
inside db.js file, first we bring mongoose to connect:
const mongoose = require('mongoose');
Second we have an async function called connectDB (because mongoose functions return promises) and then on the connect we pass our mongoose URL.
const connectDB = async () => {
const conn = await mongoose.connect('');
console.log(`mongoDB connected : ${conn.connection.host}`);
};
After that, we call this connectDB function inside index.js:
//connect to database
connectDB();
8. Mongoose Model
Create a
modelsfolder and then inside it createTodo.jsfile :server/models/Todo.js.Here we're going to store our
mongoose models.This
modelrepresents different types of collection in ourMongoDBinstance.Mongoose schema, going to define the data that actually being stored inMongoDBand this is going to take an object with the fields that we want.In our code, we use
Todomodel.thisTodo modelmeans how we interact with the todo collection then we use a method on it:
return Todo.find();
return Todo.findById(args.id);
9. Mutations
It allows us to change or mutate data like add, delete, edit data. We define our
mutationinschema.jsfile.Setting-up a mutation is like setting-up our
RootQuery. We pass throw an object toGraphQLObjectTypeand this is going to have two property:name,fields.
This fields property let us store different kind of mutations that we want to make likeaddTodo,editTodo,deleteTodo, ....
// Add todo
addTodo: {
type: TodoType,
args: {
title: { type: GraphQLNonNull(GraphQLString) },
},
resolve(parent, args) {
const todo = new Todo({
title: args.title
});
return todo.save();
}
},
For example: this addTodo property is going to be an object and takes these properties:type and args.
args: when a user makes a mutation from the frontend, then we expect them to send some kind of data or arguments.
Here, if a user wants to add a todo they're going to need send the todo title.(the fields that we want to add)
resolve: this function is where we take the argument that they send along the query. By using Todo model that, we import it before We make a new instance of todo and save it to the database.
Code:
index.js - server/index.js
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const schema = require('./schema/schema');
const app = express();
const connectDB = require('./config/db');
const cors = require('cors');
//connect to database
connectDB();
app.use(cors());
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true
}));
app.listen(5000, () => {
console.log('now listening for requests on port 5000');
});
schema.js - server/schema/schema.js
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLSchema,
GraphQLList,
GraphQLNonNull
} = require('graphql');
//Mongoose models
const Todo = require('../models/Todo.js')
//todos Typeo
const TodoType = new GraphQLObjectType({
name: 'Todo',
fields: () => ({
id: { type: GraphQLID },
title: { type: GraphQLString }
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
todos: {
type: new GraphQLList(TodoType),
resolve(parent, args) {
return Todo.find();
}
},
todo: {
type: TodoType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Todo.findById(args.id);
}
}
})
});
// Mutations
const mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
// Add todo
addTodo: {
type: TodoType,
args: {
title: { type: GraphQLNonNull(GraphQLString) },
},
resolve(parent, args) {
const todo = new Todo({
title: args.title
});
return todo.save();
}
},
// Delete Todo
deleteTodo: {
type: TodoType,
args: {
id: { type: GraphQLNonNull(GraphQLID) },
},
resolve(parent, args) {
return Todo.findByIdAndRemove(args.id)
}
},
// Edit Todo
editTodo: {
type: TodoType,
args: {
id: { type: GraphQLNonNull(GraphQLID) },
title: { type: GraphQLString },
},
resolve(parent, args) {
return Todo.findByIdAndUpdate(
args.id,
{
$set: {
title: args.title,
},
},
{ new: true }
);
},
},
}
})
module.exports = new GraphQLSchema({
query: RootQuery,
mutation
})
Todo.js- server/models/Todo.js
const mongoose = require('mongoose');
const TodoSchema = new mongoose.Schema({
title: {
type: String,
}
});
module.exports = mongoose.model('Todo', TodoSchema);
db.js - server/config/db.js
const mongoose = require('mongoose');
const connectDB = async () => {
const conn = await mongoose.connect('');
console.log(`mongoDB connected : ${conn.connection.host}`);
};
module.exports = connectDB;
Now here we go! We created a simple CRUD app with react, GraphQL, Node.js and MongoDB. In the below I put links that are helpful for me to create this project:
By the way The link to the front end section will be posted here soon!
The GraphQL tutorial playlist on The Net Ninja YouTube channel.
Full stack GraphQL, Express & React app - Traversy Media
Thank you for reading! 🍀

Top comments (0)