The Talent500 Blog
Building a Simple CRUD Application with the MERN Stack 1

Building a Simple CRUD Application with the MERN Stack

Building a Simple CRUD Application with the MERN Stack 2

The MERN stack is a powerful toolset for building web applications. Here, 

  • MongoDB is used for the database. 
  • Express is a web application framework for Node.js.
  • React is a front-end library for building user interfaces. 
  • Node.js is a JavaScript runtime. 

These technologies allow us to create a full-stack application using only JavaScript. In this blog, we will create a simple application to manage a list of items, complete with functionality to add, view, update, and delete items.

Setting Up the Development Environment

Building a Simple CRUD Application with the MERN Stack 3

Before we begin coding, we need to set up our development environment.

  • Install Node.js and npm: Make sure you have Node.js and npm installed on your machine. You can download them from the official Node.js website.
  • Install MongoDB: Download and install MongoDB from the official MongoDB website.
  • Create a project directory: Organize your project files by creating a dedicated directory for your MERN stack project.

 

bash

 

mkdir mern-crud-app

cd mern-crud-app

Backend Setup: Node.js and Express

Building a Simple CRUD Application with the MERN Stack 4

Now, let us set up the backend using Node.js and Express.

Initialize a new Node.js project:

 

bash

npm init -y

 

This command creates a package.json file with default settings.

 

Install necessary dependencies:

 

bash

npm install express mongoose body-parser cors

These packages include Express for building the web server, Mongoose for interacting with MongoDB, Body-Parser for parsing incoming request bodies, and CORS for handling cross-origin requests.

Create the server:

Create a server.js file in the project directory:

javascript

 

const express = require(‘express’);

const mongoose = require(‘mongoose’);

const bodyParser = require(‘body-parser’);

const cors = require(‘cors’);

 

const app = express();

const PORT = 5000;

 

app.use(cors());

app.use(bodyParser.json());

 

mongoose.connect(‘mongodb://localhost:27017/merncrud’, { useNewUrlParser: true, useUnifiedTopology: true });

 

const connection = mongoose.connection;

connection.once(‘open’, () => {

  console.log(‘MongoDB database connection established successfully’);

});

 

app.listen(PORT, () => {

  console.log(`Server is running on port: ${PORT}`);

});

This code sets up an Express server, connects to a MongoDB database, and listens for incoming requests on port 5000.

Define the data model:

Create a models directory and add a item.model.js file:

javascript

 

const mongoose = require(‘mongoose’);

const Schema = mongoose.Schema;

 

let Item = new Schema({

  name: {

    type: String

  },

  description: {

    type: String

  },

  price: {

    type: Number

  }

});

module.exports = mongoose.model(‘Item’, Item);

This schema defines the structure of our items, which will have a name, description, and price.

Backend API: CRUD Operations

The next step will be to set up routes to handle CRUD operations.

Set up routes:

Create a routes directory and add a item.route.js file:

javascript

 

const express = require(‘express’);

const router = express.Router();

 

let Item = require(‘../models/item.model’);

 

// Get all items

router.route(‘/’).get((req, res) => {

  Item.find((err, items) => {

    if (err) {

      console.log(err);

    } else {

      res.json(items);

    }

  });

});

 

// Get item by ID

router.route(‘/:id’).get((req, res) => {

  let id = req.params.id;

  Item.findById(id, (err, item) => {

    res.json(item);

  });

});

 

// Add a new item

router.route(‘/add’).post((req, res) => {

  let item = new Item(req.body);

  item.save()

    .then(item => {

      res.status(200).json({‘item’: ‘item added successfully’});

    })

    .catch(err => {

      res.status(400).send(‘adding new item failed’);

    });

});

 

// Update an item

router.route(‘/update/:id’).post((req, res) => {

  Item.findById(req.params.id, (err, item) => {

    if (!item)

      res.status(404).send(‘data is not found’);

    else

      item.name = req.body.name;

      item.description = req.body.description;

      item.price = req.body.price;

 

      item.save().then(item => {

        res.json(‘Item updated!’);

      })

      .catch(err => {

        res.status(400).send(‘Update not possible’);

      });

  });

});

 

// Delete an item

router.route(‘/delete/:id’).delete((req, res) => {

  Item.findByIdAndRemove({_id: req.params.id}, (err, item) => {

    if (err) res.json(err);

    else res.json(‘Item deleted successfully’);

  });

});

 

module.exports = router;

Add the routes to server.js:

 

javascript

Copy code

const itemRoutes = require(‘./routes/item.route’);

 

app.use(‘/items’, itemRoutes);

 

This code sets up the routes to handle requests for adding, reading, updating, and deleting items.

Frontend Setup: React

Now let us set up the frontend using React.

Create a React application:

 

bash

 

npx create-react-app client

cd client

npm start

 

This command creates a new React application and starts the development server.

 

Install Axios for HTTP requests:

 

bash

 

npm install axios

 

Axios is a promise-based HTTP client for making requests to the backend.

 

Set up the basic structure:

 

Create components and services directories:

 

bash

 

mkdir src/components

mkdir src/services

Creating React Components

Building a Simple CRUD Application with the MERN Stack 5

Now we will create React components for listing, creating, and updating items.

List Items Component:

Create ListItems.js in the components directory:

 

javascript

 

import React, { Component } from ‘react’;

import axios from ‘axios’;

 

export default class ListItems extends Component {

  constructor(props) {

    super(props);

    this.state = { items: [] };

  }

 

  componentDidMount() {

    axios.get(‘http://localhost:5000/items/’)

      .then(response => {

        this.setState({ items: response.data });

      })

      .catch(error => {

        console.log(error);

      });

  }

 

  render() {

    return (

      <div>

        <h3>Item List</h3>

        <table className=”table table-striped”>

          <thead>

            <tr>

              <th>Name</th>

              <th>Description</th>

              <th>Price</th>

            </tr>

          </thead>

          <tbody>

            { this.state.items.map((item, i) => (

              <tr key={i}>

                <td>{item.name}</td>

                <td>{item.description}</td>

                <td>{item.price}</td>

              </tr>

            ))}

          </tbody>

        </table>

      </div>

    );

  }

}

This component fetches the list of items from the backend and displays them in a table.

Create Item Component:

Create CreateItem.js in the components directory:

javascript

import React, { Component } from ‘react’;

import axios from ‘axios’;

 

export default class CreateItem extends Component {

  constructor(props) {

    super(props);

 

    this.onChangeName = this.onChangeName.bind(this);

    this.onChangeDescription = this.onChangeDescription.bind(this);

    this.onChangePrice = this.onChangePrice.bind(this);

    this.onSubmit = this.onSubmit.bind(this);

 

    this.state = {

      name: ”,

      description: ”,

      price: 0

    };

  }

 

  onChangeName(e) {

    this.setState({

      name: e.target.value

    });

  }

 

  onChangeDescription(e) {

    this.setState({

      description: e.target.value

    });

  }

 

  onChangePrice(e) {

    this.setState({

      price: e.target.value

    });

  }

 

  onSubmit(e) {

    e.preventDefault();

 

    const newItem = {

      name: this.state.name,

      description: this.state.description,

      price: this.state.price

    };

 

    axios.post(‘http://localhost:5000/items/add’, newItem)

      .then(res => console.log(res.data));

 

    this.setState({

      name: ”,

      description: ”,

      price: 0

    });

  }

 

  render() {

    return (

      <div style={{marginTop: 10}}>

        <h3>Create New Item</h3>

        <form onSubmit={this.onSubmit}>

          <div className=”form-group”>

            <label>Name: </label>

            <input type=”text”

                   className=”form-control”

                   value={this.state.name}

                   onChange={this.onChangeName}

                   />

          </div>

          <div className=”form-group”>

            <label>Description: </label>

            <input type=”text”

                   className=”form-control”

                   value={this.state.description}

                   onChange={this.onChangeDescription}

                   />

          </div>

          <div className=”form-group”>

            <label>Price: </label>

            <input type=”number”

                   className=”form-control”

                   value={this.state.price}

                   onChange={this.onChangePrice}

                   />

          </div>

          <div className=”form-group”>

            <input type=”submit” value=”Create Item” className=”btn btn-primary” />

          </div>

        </form>

      </div>

    );

  }

}

This component provides a form to create a new item and submits it to the backend.

Update Item Component:

Create UpdateItem.js in the components directory:

javascript

import React, { Component } from ‘react’;

import axios from ‘axios’;

 

export default class UpdateItem extends Component {

  constructor(props) {

    super(props);

 

    this.onChangeName = this.onChangeName.bind(this);

    this.onChangeDescription = this.onChangeDescription.bind(this);

    this.onChangePrice = this.onChangePrice.bind(this);

    this.onSubmit = this.onSubmit.bind(this);

 

    this.state = {

      name: ”,

      description: ”,

      price: 0

    };

  }

 

  componentDidMount() {

    axios.get(‘http://localhost:5000/items/’+this.props.match.params.id)

      .then(response => {

        this.setState({

          name: response.data.name,

          description: response.data.description,

          price: response.data.price

        })   

      })

      .catch(error => {

        console.log(error);

      });

  }

 

  onChangeName(e) {

    this.setState({

      name: e.target.value

    });

  }

 

  onChangeDescription(e) {

    this.setState({

      description: e.target.value

    });

  }

 

  onChangePrice(e) {

    this.setState({

      price: e.target.value

    });

  }

 

  onSubmit(e) {

    e.preventDefault();

    const obj = {

      name: this.state.name,

      description: this.state.description,

      price: this.state.price

    };

    axios.post(‘http://localhost:5000/items/update/’+this.props.match.params.id, obj)

      .then(res => console.log(res.data));

    

    this.props.history.push(‘/’);

  }

 

  render() {

    return (

      <div>

        <h3>Update Item</h3>

        <form onSubmit={this.onSubmit}>

          <div className=”form-group”> 

            <label>Name: </label>

            <input type=”text”

                   className=”form-control”

                   value={this.state.name}

                   onChange={this.onChangeName}

                   />

          </div>

          <div className=”form-group”>

            <label>Description: </label>

            <input type=”text”

                   className=”form-control”

                   value={this.state.description}

                   onChange={this.onChangeDescription}

                   />

          </div>

          <div className=”form-group”>

            <label>Price: </label>

            <input type=”number”

                   className=”form-control”

                   value={this.state.price}

                   onChange={this.onChangePrice}

                   />

          </div>

          <div className=”form-group”>

            <input type=”submit” value=”Update Item” className=”btn btn-primary” />

          </div>

        </form>

      </div>

    );

  }

}

This component fetches the item to be updated and provides a form to update its details.

Connecting Frontend to Backend

Building a Simple CRUD Application with the MERN Stack 6

Finally, let us connect the frontend to the backend.

Update React App:

Modify App.js:

javascript

 

import React from ‘react’;

import { BrowserRouter as Router, Route, Link } from ‘react-router-dom’;

import ‘bootstrap/dist/css/bootstrap.min.css’;

 

import CreateItem from ‘./components/CreateItem’;

import ListItems from ‘./components/ListItems’;

import UpdateItem from ‘./components/UpdateItem’;

 

function App() {

  return (

    <Router>

      <div className=”container”>

        <nav className=”navbar navbar-expand-lg navbar-light bg-light”>

          <Link to=”/” className=”navbar-brand”>MERN-Stack CRUD App</Link>

          <div className=”collapse navbar-collapse”>

            <ul className=”navbar-nav mr-auto”>

              <li className=”navbar-item”>

                <Link to=”/” className=”nav-link”>Items</Link>

              </li>

              <li className=”navbar-item”>

                <Link to=”/create” className=”nav-link”>Create Item</Link>

              </li>

            </ul>

          </div>

        </nav>

        <br/>

        <Route path=”/” exact component={ListItems} />

        <Route path=”/edit/:id” component={UpdateItem} />

        <Route path=”/create” component={CreateItem} />

      </div>

    </Router>

  );

}

export default App;

The above sets up the routing for our React application. It allows us to navigate between the list, create, and update item pages.

Conclusion

By following this tutorial, you have built a simple CRUD application using the MERN stack. You have learned how to set up a development environment, create a backend with Node.js and Express, connect it to a MongoDB database, and build a frontend with React. This application serves as a foundation for more complex projects, and you can expand it by adding more features such as user authentication, advanced search, and more.

0
Taniya Pan

Taniya Pan

Add comment