Create database connection with Mongodb with CRUD operations in ReactJS

A database is a store where we can store data as we need. In a database, data can be added, updated, removed, and deleted. There is various database that we can use as web-developer. MongoDB is one of those.

In this article, we will learn how to make a connection to a MongoDB database to our backend server and we will perform some CRUD operations here. Below are the topics that we will be covering here,

  • Create a MongoDB cluster
  • Store some data in MongoDB
  • Install required dependencies for node.js
  • Create the API
  • Connect the API with the front end.

Create MongoDB cluster

  • Click on Build Databse

  • Give a username and password to the cluster

  • Set IP address

  • Now click on Browse Collection

  • Create database and collection name

Store some data in MongoDB

  • Insert data

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net",
    "company": {
      "name": "Deckow-Crist",
      "catchPhrase": "Proactive didactic contingency",
      "bs": "synergize scalable supply-chains"
    }
  },
  {
    "id": 3,
    "name": "Clementine Bauch",
    "username": "Samantha",
    "email": "Nathan@yesenia.net",
    "address": {
      "street": "Douglas Extension",
      "suite": "Suite 847",
      "city": "McKenziehaven",
      "zipcode": "59590-4157",
      "geo": {
        "lat": "-68.6102",
        "lng": "-47.0653"
      }
    },
    "phone": "1-463-123-4447",
    "website": "ramiro.info",
    "company": {
      "name": "Romaguera-Jacobson",
      "catchPhrase": "Face to face bifurcated interface",
      "bs": "e-enable strategic applications"
    }
  },
  {
    "id": 4,
    "name": "Patricia Lebsack",
    "username": "Karianne",
    "email": "Julianne.OConner@kory.org",
    "address": {
      "street": "Hoeger Mall",
      "suite": "Apt. 692",
      "city": "South Elvis",
      "zipcode": "53919-4257",
      "geo": {
        "lat": "29.4572",
        "lng": "-164.2990"
      }
    },
    "phone": "493-170-9623 x156",
    "website": "kale.biz",
    "company": {
      "name": "Robel-Corkery",
      "catchPhrase": "Multi-tiered zero tolerance productivity",
      "bs": "transition cutting-edge web services"
    }
  },
  {
    "id": 5,
    "name": "Chelsey Dietrich",
    "username": "Kamren",
    "email": "Lucio_Hettinger@annie.ca",
    "address": {
      "street": "Skiles Walks",
      "suite": "Suite 351",
      "city": "Roscoeview",
      "zipcode": "33263",
      "geo": {
        "lat": "-31.8129",
        "lng": "62.5342"
      }
    },
    "phone": "(254)954-1289",
    "website": "demarco.info",
    "company": {
      "name": "Keebler LLC",
      "catchPhrase": "User-centric fault-tolerant solution",
      "bs": "revolutionize end-to-end systems"
    }
  },
  {
    "id": 6,
    "name": "Mrs. Dennis Schulist",
    "username": "Leopoldo_Corkery",
    "email": "Karley_Dach@jasper.info",
    "address": {
      "street": "Norberto Crossing",
      "suite": "Apt. 950",
      "city": "South Christy",
      "zipcode": "23505-1337",
      "geo": {
        "lat": "-71.4197",
        "lng": "71.7478"
      }
    },
    "phone": "1-477-935-8478 x6430",
    "website": "ola.org",
    "company": {
      "name": "Considine-Lockman",
      "catchPhrase": "Synchronised bottom-line interface",
      "bs": "e-enable innovative applications"
    }
  },
  {
    "id": 7,
    "name": "Kurtis Weissnat",
    "username": "Elwyn.Skiles",
    "email": "Telly.Hoeger@billy.biz",
    "address": {
      "street": "Rex Trail",
      "suite": "Suite 280",
      "city": "Howemouth",
      "zipcode": "58804-1099",
      "geo": {
        "lat": "24.8918",
        "lng": "21.8984"
      }
    },
    "phone": "210.067.6132",
    "website": "elvis.io",
    "company": {
      "name": "Johns Group",
      "catchPhrase": "Configurable multimedia task-force",
      "bs": "generate enterprise e-tailers"
    }
  },
  {
    "id": 8,
    "name": "Nicholas Runolfsdottir V",
    "username": "Maxime_Nienow",
    "email": "Sherwood@rosamond.me",
    "address": {
      "street": "Ellsworth Summit",
      "suite": "Suite 729",
      "city": "Aliyaview",
      "zipcode": "45169",
      "geo": {
        "lat": "-14.3990",
        "lng": "-120.7677"
      }
    },
    "phone": "586.493.6943 x140",
    "website": "jacynthe.com",
    "company": {
      "name": "Abernathy Group",
      "catchPhrase": "Implemented secondary concept",
      "bs": "e-enable extensible e-tailers"
    }
  },
  {
    "id": 9,
    "name": "Glenna Reichert",
    "username": "Delphine",
    "email": "Chaim_McDermott@dana.io",
    "address": {
      "street": "Dayna Park",
      "suite": "Suite 449",
      "city": "Bartholomebury",
      "zipcode": "76495-3109",
      "geo": {
        "lat": "24.6463",
        "lng": "-168.8889"
      }
    },
    "phone": "(775)976-6794 x41206",
    "website": "conrad.com",
    "company": {
      "name": "Yost and Sons",
      "catchPhrase": "Switchable contextually-based project",
      "bs": "aggregate real-time technologies"
    }
  },
  {
    "id": 10,
    "name": "Clementina DuBuque",
    "username": "Moriah.Stanton",
    "email": "Rey.Padberg@karina.biz",
    "address": {
      "street": "Kattie Turnpike",
      "suite": "Suite 198",
      "city": "Lebsackbury",
      "zipcode": "31428-2261",
      "geo": {
        "lat": "-38.2386",
        "lng": "57.2232"
      }
    },
    "phone": "024-648-3804",
    "website": "ambrose.net",
    "company": {
      "name": "Hoeger LLC",
      "catchPhrase": "Centralized empowering task-force",
      "bs": "target end-to-end models"
    }
  }
]

Install required dependencies for Node.js

  • Create a folder for the backend server

  • Open the command prompt and run npm init -y command. It will add the package.json file to the folder.
  • Run the below command to the same folder in the command prompt
npm i express mongodb cors

express will install the dependencies for express.js, mongodb will allow us to use the database on our server, and cors used for the cross-platform policy so that the server can connect to the front end without interruption.

  • Create a file named, index.js

  • Write the below code in index.js
const express = require('express');
const app = express();
const cors = require('cors')
const port = process.env.PORT || 5000;
app.use(cors())
app.use(express.json())

app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

Here, the port defines the server route, in which path the data will be rendered. As we can see it is in 5000. So if we run http://localhost:5000/ , we will be able to ‘Hello world.

  • Declare the MongoDB URI and MongoDB client.
const uri = "mongodb+srv://userInfoDB:<password>@cluster0.7wjys8r.mongodb.net/?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });

Note: in the place of <password> you have to put the password of the mongodb cluster.

  • Create a run function
async function run() {
    try {
        await client.connect()
    } finally {
    }
}

run().catch(console.dir);
const { MongoClient, ServerApiVersion } = require('mongodb');
const express = require('express');
const app = express();
const cors = require('cors')
const port = process.env.PORT || 5000;
app.use(cors())
app.use(express.json())






const uri = "mongodb+srv://userInfoDB:<password>@cluster0.7wjys8r.mongodb.net/?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });


async function run() {
    try {
        await client.connect()
    } finally {
    }
}
run().catch(console.dir);






app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

Inside the run function, we will create our API endpoint.

Create the API

  • Store all the data from the database in a variable
const useCollection = client.db('userInfo').collection('name');
  • Use the get method to read all the data from the database.
app.get('/users', async (req, res) => {
            const query = {}
            const result = await userCollection.find(query).toArray()
            res.send(result)
        })

The full code will look like the below one,

const { MongoClient, ServerApiVersion } = require('mongodb');
const express = require('express');
const app = express();
const cors = require('cors')
const port = process.env.PORT || 5000;
app.use(cors())
app.use(express.json())





// add your password here at the <password>
const uri = "mongodb+srv://userInfoDB:<password>@cluster0.7wjys8r.mongodb.net/?retryWrites=true&w=majority";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true, serverApi: ServerApiVersion.v1 });


async function run() {
    try {
        await client.connect()
        const userCollection = client.db('userInfo').collection('name');

        app.get('/users', async (req, res) => {
            const query = {}
            const result = await userCollection.find(query).toArray()
            res.send(result)
        })


    } finally {
    }
}
run().catch(console.dir);






app.get('/', (req, res) => {
    res.send('Hello World!')
})

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

After running the server, if we run the localhost, we will get an array of users which is coming from the database.

CRUD Operation

Create, Read, Update and Delete… all together, it is CRUD.

In MongoDB, a user can add, read, delete and update the data as the project requires.

Create Data (Add data)

  • Add a button in the working project component.

Note: to know more about creating a table and fetching data from MongoDB, Please read this article.

<button className="btn my-8">Add User</button>
import React, { useEffect, useState } from 'react';

const TableData = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        fetch('http://localhost:5000/users')
            .then(res => res.json())
            .then(data => setUsers(data))
    }, []);

    return (
        <div>
            <h1 className="text-4xl text-center my-10">
                Dynamic Data in Table
            </h1>
            {/* add user */}

            {/* button */}


            <div className='w-1/2 mx-auto'>
                <button className="btn my-8">Add User</button>
                <div class="overflow-x-auto">
                    <table class="table w-full">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                        <tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                    </tr>
                                )
                            }

                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    );
};

export default TableData;

  • Add an onClick() event handler to that button.
<button onClick={handleAddUser} className="btn my-8">Add User</button>
  • Add an input field with the button
<input type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
<button onClick={handleAddUser} className="btn my-8">Add User</button>

  • Get the typed value inside from that input field with an onChange() event handler.
// set input value
    const [name, setName] = useState('')
<input onChange={(e) => setName(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
  • Create a post method API in the backend.
// create a post method
        app.post('/users', async (req, res) => {
            const data = req.body;
            // console.log(data)
            const doc = data;
            const result = await userCollection.insertOne(doc);
            res.send(result)
        })

Here, we are creating a post API with the pathname, ‘/users’. We will get some data as an object from request body. We are keeping those data to a variable called data. After storing that data to a new variable doc, we are inserting that object to our collection and after inserting, we are sending the result to the frontend.

  • Create a POST method into the button handler that we created in the frontend.
const handleAddUser = () => {
        fetch('http://localhost:5000/users', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }

Here, we are sending the input data as an object to our API endpoint.

import React, { useEffect, useState } from 'react';

const TableData = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        fetch('http://localhost:5000/users')
            .then(res => res.json())
            .then(data => setUsers(data))
    }, []);

    // set input value
    const [name, setName] = useState('');
    console.log(name)

    const handleAddUser = () => {
        fetch('http://localhost:5000/users', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }

    return (
        <div>
            <h1 className="text-4xl text-center my-10">
                Dynamic Data in Table
            </h1>
            {/* add user */}

            {/* button */}


            <div className='w-1/2 mx-auto'>
                <input onChange={(e) => setName(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                <button onClick={handleAddUser} className="btn my-8">Add User</button>
                <div class="overflow-x-auto">
                    <table class="table w-full">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                        <tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                    </tr>
                                )
                            }

                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    );
};

export default TableData;

If we check the MongoDB data collection, we will be able to see the added data there.

Read Data

As we have added the user to the API endpoint ‘/users’ and we are fetching data from there, after refreshing the page, we will be able to see the data to our localhost.

import React, { useEffect, useState } from 'react';

const TableData = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        fetch('http://localhost:5000/users')
            .then(res => res.json())
            .then(data => setUsers(data))
    }, []);

    // set input value
    const [name, setName] = useState('');
    console.log(name)

    const handleAddUser = () => {
        fetch('http://localhost:5000/users', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }

    return (
        <div>
            <h1 className="text-4xl text-center my-10">
                Dynamic Data in Table
            </h1>
            {/* add user */}

            {/* button */}


            <div className='w-1/2 mx-auto'>
                <input onChange={(e) => setName(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                <button onClick={handleAddUser} className="btn my-8">Add User</button>
                <div class="overflow-x-auto">
                    <table class="table w-full">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                            </tr>
                        </thead>
                        <tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                    </tr>
                                )
                            }

                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    );
};

export default TableData;
  • Refresh the page on the browser.

Update data

To update the data, let’s add an input box and an update button to all the data that we are fetching.

  • Add an input box and an button to each <tr>
<tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                        <td>
                                            <input onChange={(e) => setUpdate(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                                            <button onClick={()=>handleUpdate(user._id)} className='btn btn-sm'>Update</button>
                                        </td>
                                    </tr>
                                )
                            }

</tbody>
import React, { useEffect, useState } from 'react';

const TableData = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        fetch('http://localhost:5000/users')
            .then(res => res.json())
            .then(data => setUsers(data))
    }, []);

    // set input value
    const [name, setName] = useState('');
    console.log(name)

    const handleAddUser = () => {
        fetch('http://localhost:5000/users', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }
    // handle update
    const [update, setUpdate] = useState('')
    const handleUpdate = (e) => {

    }

    return (
        <div>
            <h1 className="text-4xl text-center my-10">
                Dynamic Data in Table
            </h1>
            {/* add user */}

            {/* button */}


            <div className='w-2/3 mx-auto'>
                <input onChange={(e) => setName(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                <button onClick={handleAddUser} className="btn my-8">Add User</button>
                <div class="overflow-x-auto">
                    <table class="table w-full">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                                <th>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                        <td>
                                            <input onChange={(e) => setUpdate(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                                            <button onClick={handleUpdate} className='btn btn-sm'>Update</button>
                                        </td>
                                    </tr>
                                )
                            }

                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    );
};

export default TableData;

  • Add an event handler to the button. And onChange event to the input to store the data on a state variable.
<input onChange={(e) => setUpdate(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />

<button onClick={()=>handleUpdate(user._id)} className='btn btn-sm'>Update</button>

Note: we will get the user id in the parameter of the onClick handler with (user._id)

  • Create a PATCH method for the backend
// update 
       app.patch('/users/:id', async (req, res) => {
           const id = req.params.id;
           const filter = { _id: ObjectId(id) };
           const data = req.body;
           // console.log(data)
           const updateDoc = {
               $set: data
           };
           const result = await userCollection.updateOne(filter, updateDoc);
           res.send(result)
       })

here, we have to send a dynamic API endpoint with ‘/:id’ because we will update one specific item and we have to find it in the database.

  • Create a PATCH method in the frontend inside the onClick handler of update button.
// handle update
   const [update, setUpdate] = useState('')

   const handleUpdate = (id) => {
       console.log(update)
       // console.log(id)
       fetch(`http://localhost:5000/users/${id}`, {
           method: "PATCH",
           headers: {
               "Content-type": "application/json"
           },
           body: JSON.stringify({ name: update })
       })
           .then(res => res.json())
           .then(data => console.log(data))
   }

Here, we are sending the updated data as an object to the backend.

import React, { useEffect, useState } from 'react';

const TableData = () => {
    const [users, setUsers] = useState([]);
    useEffect(() => {
        fetch('http://localhost:5000/users')
            .then(res => res.json())
            .then(data => setUsers(data))
    }, []);

    // set input value
    const [name, setName] = useState('');
    console.log(name)

    const handleAddUser = () => {
        fetch('http://localhost:5000/users', {
            method: "POST",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }
    // handle update
    const [update, setUpdate] = useState('')

    const handleUpdate = (id) => {
        console.log(update)
        // console.log(id)
        fetch(`http://localhost:5000/users/${id}`, {
            method: "PATCH",
            headers: {
                "Content-type": "application/json"
            },
            body: JSON.stringify({ name: update })
        })
            .then(res => res.json())
            .then(data => console.log(data))
    }

    return (
        <div>
            <h1 className="text-4xl text-center my-10">
                Dynamic Data in Table
            </h1>
            {/* add user */}

            {/* button */}


            <div className='w-2/3 mx-auto'>
                <input onChange={(e) => setName(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                <button onClick={handleAddUser} className="btn my-8">Add User</button>
                <div class="overflow-x-auto">
                    <table class="table w-full">
                        <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                                <th>Action</th>
                            </tr>
                        </thead>
                        <tbody>
                            {
                                users.map(user =>
                                    <tr>
                                        <th>{user.id}</th>
                                        <td>{user.name}</td>
                                        <td>
                                            <input onChange={(e) => setUpdate(e.target.value)} type="text" placeholder="Type here" class="input input-bordered w-full max-w-xs mx-2" />
                                            <button onClick={() => handleUpdate(user._id)} className='btn btn-sm'>Update</button>
                                        </td>
                                    </tr>
                                )
                            }

                        </tbody>
                    </table>
                </div>
            </div>

        </div>
    );
};

export default TableData;

After refreshing the page,

The name has been updated.

This is how we can connect MongoDB to our server and run CRUD operations.