Create CRUD application using MERN stack (MongoDB, Express, React, Node.js)

Category
Tutorial
Reading
5 mins
Views
363
Posting
08 Jul 2024

Node.js is an open-source javascript environment used to run JavaScript-based applications on a server. Before Node.js was created, JavaScript was often used in the frontend to make websites interactive. When Node.js was created, the advantage of Node.js is that it can be run both on the server and for the frontend, making it easier for developers to create web-based applications with only 1 programming language, namely Javascript. Node.js only handles the server side, for the frontend itself we need additional libraries such as Express, React or Next.js.

In this tutorial, I will create a simple example of creating a Node.js-based CRUD with MERN stacks, namely MongoDB, Express, React and Node.js. MERN stack is very popular among Full Stack Developers because it is very efficient in building web-based applications and is widely used in companies and individuals. And it is also very suitable to use if you are developing an API application that is light and has fast performance.

 

 

Create a CRUD application using MERN stack - Genelify

 

1. What is MERN stack

Before getting into the main material, you might ask what MERN stack are? MERN stack became popular when React.js began to be favored by developers by running web applications, unlike other programming languages that mostly use MySQL to store their data, developers who build applications with Node.js prefer to use MongoDB to store their data. MERN itself stands for MongoDB, Express, React and Node.js, which means a set of technologies to create powerful web applications that run from the server side and frontend using Javascript.

Usually fullstack developers use the MERN stack to create web applications because it is only in 1 programming language, namely JavaScript, which can handle the server side and frontend.

 

2. Creating database and collection in MongoDB

Previously we had to set up the MongoDB database first, to make it easier to use I recommend using MongoDB Compass, create a new database and collection on the database server, set the database name and collection name as follows:

 

Create a CRUD application using MERN stack - Genelify

 

If your computer doesn't have MongoDB installed, you can download it first on the official website https://www.mongodb.com/try/download/shell, install as usual and don't forget to install with MongoDB compass to make it easier to manage with a GUI (Graphical User Interface).

 

3. Start the project

After we know what the MERN stack is, we will get into the main material, namely making a simple CRUD using this technology stack, but make sure you have previously installed Node.js and MongoDB on your computer, I recommend specifically for MongoDB, you also install MongoDB Compass for easier User Interface and debugging. Please open your editor code, create a new project folder called MERN, this folder will hold many files related to the CRUD application, after you have opened the editor code and created a project folder with the name MERN, enter the project folder and run the terminal, enter the following command to initialize our Node.js project: 

npm init -y

Next we need several libraries to run our CRUD application such as Express, mongoose, cors, and body-parser, please enter the following command in the terminal:

npm install express mongoose body-parser cors

Wait until the installation process is complete, if all is complete then the folder structure will be like this:

MERN/
├── node_modules/
├── package-lock.json 
└── package.lock 

Next we will create a new file with the name server.js in the root of the MERN folder, this server.js functions to handle incoming HTTP requests related to our CRUD application such as GET, PUT, DELETE, UPDATE, run the library that we have installed before and set the port in our application. Please copy and paste the following code:

// Create a Basic CRUD application using MERN stack - Genelify
// server.js

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cors = require('cors');

const app = express();
const PORT = process.env.PORT || 5000;

// Middleware
app.use(cors());
app.use(bodyParser.json());

// MongoDB connection
mongoose.connect('mongodb://localhost:27017/merncrud', { useNewUrlParser: true, useUnifiedTopology: true })
    .then(() => console.log('MongoDB connected'))
    .catch(err => console.log(err));

// Define a schema and model
const itemSchema = new mongoose.Schema({
    name: String,
    description: String,
});

const Item = mongoose.model('Item', itemSchema);

// Routes
app.get('/items', async (req, res) => {
    try {
        const items = await Item.find();
        res.json(items);
    } catch (err) {
        res.status(500).json({ message: err.message });
    }
});

app.post('/items', async (req, res) => {
    const item = new Item({
        name: req.body.name,
        description: req.body.description,
    });

    try {
        const newItem = await item.save();
        res.status(201).json(newItem);
    } catch (err) {
        res.status(400).json({ message: err.message });
    }
});

app.put('/items/:id', async (req, res) => {
    try {
        const item = await Item.findById(req.params.id);
        if (item) {
            item.name = req.body.name;
            item.description = req.body.description;
            const updatedItem = await item.save();
            res.json(updatedItem);
        } else {
            res.status(404).json({ message: 'Item not found' });
        }
    } catch (err) {
        res.status(400).json({ message: err.message });
    }
});

app.delete('/items/:id', async (req, res) => {
    try {
        const item = await Item.findById(req.params.id);
        if (!item) {
            return res.status(404).json({ message: 'Item not found' });
        }

        await item.deleteOne();
        res.json({ message: 'Item deleted' });
    } catch (err) {
        console.error('Error deleting item:', err);
        res.status(500).json({ message: 'Internal server error' });
    }
});

app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

With this server.js is ready to run later when we have finished creating a setup for the frontend using React. Next we will create a project for the React application.

 

4. Setup frontend with React

Still in the MERN root folder, open your terminal and create the React application on our frontend by entering the following command:

npx create-react-app client

Wait until the installation process is complete, and a new folder will be created, namely the client folder, this client folder contains the React application that was installed earlier, but we need 1 more additional library, namely Axios, for those who are familiar with JavaScript, they must know what Axios is, Axios itself functions mainly to interact with our server with the HTTP protocol, for example when users will add data, change data or delete data, the role of Axios is very important. Then the folder on MERN will be like this:

MERN/
├── client/
├── node_modules/
├── package-lock.json 
├── package.json 
└── server.js

To install Axios, enter the client folder with the command in your terminal cd client, then enter the following command:

npm install axios

Wait until the installation process is complete and the last stage we will create components to handle our CRUD application with React such as displaying data, adding data and deleting data. Open the App.js file in the client/src folder, then replace the previous code with the following code:

// Create a Basic CRUD application using MERN stack - Genelify
// App.js

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

const PORT = process.env.PORT || 5000;

const App = () => {
    const [items, setItems] = useState([]);
    const [name, setName] = useState('');
    const [description, setDescription] = useState('');
    const [editingItem, setEditingItem] = useState(null);

    useEffect(() => {
        fetchItems();
    }, []);

    const fetchItems = async () => {
        try {
            const response = await axios.get(`http://localhost:${PORT}/items`);
            setItems(response.data);
        } catch (error) {
            console.error('Error fetching items:', error);
        }
    };

    const addItem = async () => {
        const newItem = { name, description };
        try {
            const response = await axios.post(`http://localhost:${PORT}/items`, newItem);
            setItems([...items, response.data]);
            setName('');
            setDescription('');
        } catch (error) {
            console.error('Error adding item:', error);
        }
    };

    const editItem = async (id) => {
        const updatedItem = { name, description };
        try {
            const response = await axios.put(`http://localhost:${PORT}/items/${id}`, updatedItem);
            setItems(items.map(item => (item._id === id ? response.data : item)));
            setEditingItem(null);
            setName('');
            setDescription('');
        } catch (error) {
            console.error('Error editing item:', error);
        }
    };

    const deleteItem = async (id) => {
        try {
            await axios.delete(`http://localhost:${PORT}/items/${id}`);
            const updatedItems = items.filter((item) => item._id !== id);
            setItems(updatedItems);
        } catch (error) {
            console.error('Error deleting item:', error);
        }
    };

    return (
        <div className="App">
            <h1>CRUD with MERN Stack</h1>
            <div>
                <input 
                    type="text"
                    placeholder="Name"
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                />
                <input 
                    type="text"
                    placeholder="Description"
                    value={description}
                    onChange={(e) => setDescription(e.target.value)}
                />
                <button onClick={editingItem ? () => editItem(editingItem) : addItem}>
                    {editingItem ? 'Update Item' : 'Add Item'}
                </button>
            </div>
            <ul>
                {items.map(item => (
                    <li key={item._id}>
                        {item.name} - {item.description}
                        <button onClick={() => {
                            setName(item.name);
                            setDescription(item.description);
                            setEditingItem(item._id);
                        }}>Edit</button>
                        <button type="button" onClick={() => deleteItem(item._id)}>Delete</button>
                    </li>
                ))}
            </ul>
        </div>
    );
};

export default App;

When finished, congratulations we have finished making a simple CRUD with the MERN stack, to test our application, open CMD on your computer, then run the following command to run MongoDB, enter the MERN root folder, then run it with the command:

node server.js

Next we will run our React application by entering the client folder, then run the following command:

npm start

If the display is the same as the image below, then the CRUD application is ready to use, please if you want to change or add features to this application such as using tailwind or others.

 

Create a CRUD application using MERN stack - Genelify - GET

Get data

 

Create a CRUD application using MERN stack - Genelify - UPDATE

Update data

 

Create a CRUD application using MERN stack - Genelify - PUT

Put data

 

Conclusion

MERN stack is very suitable for use if you are a Full Stack developer who wants speed in the development process on the website, because by using MERN stack you only focus on 1 programming language, namely JavaScript, added support from a very large community so you don't need to worry if there are problems or difficulties in the development process of your website.

Share