React + GraphQL CRUD
Tags: react, graphql, node, crud
Published: 2023-08-28 12:26:54

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](https://github.com/NeginSal/CRUD-react-graphql)



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5wf0lpgtc1hpyossfe3w.png)


### **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` because`express` 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
}));
```
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 }
  })
});
```
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 Query`and 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);
      }
    }
  })
});
```
---

**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 `models` folder and then inside it create`Todo.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);
```

---

**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();
      }
    },
```

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.](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwiz9OO1-vyAAxW4UKQEHTr2AO4QwqsBegQIDRAF&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DY0lDGjwRYKw&usg=AOvVaw0ePBhWrvcC9ki2k9jy_CeP&opi=89978449)

[Full stack GraphQL, Express & React app - Traversy Media](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwj-wcL9-vyAAxVQsKQKHbK2C_IQwqsBegQIDRAF&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DBcLNfwF04Kw&usg=AOvVaw1eGn_RxD8L386s1UIHAt9-&opi=89978449)

Thank you for reading! 🍀