DEV Community

Cover image for React + GraphQL CRUD
Negin Saljooghi
Negin Saljooghi

Posted on

React + GraphQL CRUD

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

Image description

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 app and 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 main graphql package which is a JavaScript implantation of GraphQL, the second one is a package that help our express app to interact with GraphQL becauseexpress doesn't understand GraphQL(require express-graphql module(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
}));
Enter fullscreen mode Exit fullscreen mode

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 Schema to describe how the data in our graph will looks like, inside this file we're going to define our schema.
    Schema describe the object type and the relations between these object types, how we can read data and interact with them.

  • Require the GraphQL. We install this package before.

  • We define ObjectType and define what this ObjectType is 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 }
  })
});
Enter fullscreen mode Exit fullscreen mode

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 fields of this Root Queryand each of this fields going to be a type of RootQuery.first one is going to be a query for list of todos and the second is for one todo and the argument that we expected to get along with this query is id.

  • Also, we have type and resolve function for each field.
    resolve function : 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. parent coming 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);
      }
    }
  })
});
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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}`);
};
Enter fullscreen mode Exit fullscreen mode

After that, we call this connectDB function inside index.js:

//connect to database
connectDB();
Enter fullscreen mode Exit fullscreen mode

8. Mongoose Model

  • Create a models folder and then inside it createTodo.js file :server/models/Todo.js.

  • Here we're going to store our mongoose models.

  • This model represents different types of collection in our MongoDB instance.Mongoose schema, going to define the data that actually being stored in MongoDB and this is going to take an object with the fields that we want.

  • In our code, we use Todo model.this Todo model means how we interact with the todo collection then we use a method on it:

return Todo.find();
return Todo.findById(args.id);
Enter fullscreen mode Exit fullscreen mode

9. Mutations

  • It allows us to change or mutate data like add, delete, edit data. We define our mutation in schema.js file.

  • Setting-up a mutation is like setting-up our RootQuery. We pass throw an object to GraphQLObjectType and this is going to have two property: name, fields.
    This fields property let us store different kind of mutations that we want to make like addTodo, 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();
      }
    },
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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
})
Enter fullscreen mode Exit fullscreen mode

Todo.js- server/models/Todo.js

const mongoose = require('mongoose');

const TodoSchema = new mongoose.Schema({
  title: {
    type: String,
  }
});

module.exports = mongoose.model('Todo', TodoSchema);
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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)