Connecting React to MongoDB: Easy Methods Explained

Connecting React to MongoDB: Easy Methods Explained

Database

It is a place where data is stored persistently.

Databases were are created using protocols that browsers don’t understand.

Database supports 4 operations(CRUD):

  1. Create

  2. Read

  3. Update

  4. Delete

MongoDB

MongoDB is a popular, open-source, NoSQL database management system designed for handling large amounts of data in a flexible and scalable manner.

MongoDB stores data in flexible, JSON-like documents, which means fields can vary from document to document and data structure can be changed over time.

Let's create an app that stores todo list and user information.

File Structure:

Firstly we define the schema of the database in db.js file

// db.js

const mongoose = require('mongoose')
mongoose.connect('YOUR_MONGODB_URL')

const user = new mongoose.Schema({
   email: String,
   firstname: String,
   lastname: String,
   password: String
})

const todo = new mongoose.Schema({
  userId:{
     type: mongoose.Schema.types.objectId,
     ref: 'user'
  },

  title: String,
  completed: Boolean
})

const User = mongoose.model('User', user)
const Todo = mongoose.model('Todo', todo)

module.exports={
  User,
  Todo
}

Now next we have to create the routes.

First create index.js file.

// index.js

const express = require('express')
const cors = require('cors')

const app = express()

app.use(cors())
app.use(express.json())

app.listen(3000, ()=>{
  console.log('Server running at 3000')
})

Create a config.js file to store your jwt secret key.

// config.js

module.exports={
  JWT_SECRET: 'hello'
}

Let's setup user routes.

// routes/users.js

const express = require('express')
const router = express.Router()
const {User} = require('../db.js')
const {JWT_SECRET} = require('../config')
const zod = require('zod')
const jwt = require('jsonwebtoken')

const signupBody = zod.object({
   email: zod.string().email(),
   firstname: zod.string(),
   lastname: zod.string(),
   password: zod.string()
})

const signinBody = zod.object({
  email: zod.string().email(),
  password: zod.string()
})

router.post('/signup',async(req, res)=>{
   const {success} = signupBody.safeParse(req.body)

   if(!success){
      return res.status(411).json({
          message:'Email already taken'
      })
   }

   const ExistingUser = await User.findOne({
       email: req.body.email,
       firstname: req.body.firstname,
       lastname: req.body.lastname,
       password: req.body.password
   })

   if(ExistingUser){
        return res.status(411).json({
             message: "Account already exists"
        })
   }

   const user = await User.create({
       email: req.body.email,
       firstname: req.body.firstname,
       lastname: req.body.lastname,
       password: req.body.password
   })

   const userId = user._id

   const token = jwt.sign({ userId },JWT_SECRET)

    res.json({
      message: "Account created successfully",
      token: token
    })
})

router.post('/signin', async(req, res)=>{
    const {success} = signinBody.safeParse(req.body)

    if(!success){
       return res.status(411).json({
           message: 'User does not exist'
       })
    }

    const user = User.findOne({
        email: req.body.email,
        password: req.body.password
    })

    if(user){
        const token = jwt.sign({ userId: user._id }, JWT_SECRET)
        return res.status(200).json({
           message: 'Sign in successful',
           token: token
        }) 

    }

    res.status(400).json({
      message: 'Invalid email or password'
   })
})

module.exports= router

Next we setup Todo routes. Before that we need to setup our middlewares.

// middleware.js

const {JWT_SECRET} = require('../config.js')
const jwt = jsonwentoken

const middleware = (req, res, next)=>{
  const authHeader = req.headers.authorization

  if(!authHeader || !authHeader.startsWith('Bearer')){
      return req.status(400).json({
          message:"Unauthorized"
      })
  }

  const token = authHeader.split(' ')[1]

  try{
      const payload = jwt.verify(token, JWT_SECRET)
      req.userId = payload.userId
      next()
  }catch(err){
      return res.json({
          message: 'Invalid'
      })
  }

}
module.exports = middleware
// routes/ todo.js

const express = require('express')
const {Todo} = require('../db')
const router = express.Router()
const {middleware} = require('../middleware')

router.post('/addTodo', async(req, res)=>{
    const result = req.body

    const todo =await Todo.create({
        userId: req.userId,
        title: req.title,
        completed: req.completed
    })

    res.status(200).json({
        message:"Todo addded"
        result
    })
})

router.get('/todolist', middleware, async(req, res)=>{
    const todo = await Todo.find({
        userId: req.userId
    })

    res.status(200).json({
        todo
    })

})

module.exports = router

Next we create index.js for router to route each request to their specific routes.

// routes/index.js

const express = require('express')
const userRouter = require('./users')
const todoRouter = require('./todo')
const router = express.Router()

router.use('/users', userRouter)
router.use('/todo', todoRouter)

module.exports = router

Then we can update our original index.js.

// index.js

const express = require('express')
const cors = require('cors')
const router = require('../routes/index')

const app = express()

app.use(cors())
app.use(express.json())

app.use('/api', router)

app.listen(3000, ()=>{
  console.log('Server running at 3000')
})

Testing the backend.

Did you find this article valuable?

Support Reuben's blog by becoming a sponsor. Any amount is appreciated!