Building a Simple CRUD Application with MERN Stack: A Step-by-Step Tutorial

MERN stack is a powerful web development stack that combines MongoDB, Express.js, React, and Node.js. In this tutorial, we will build a simple CRUD (Create, Read, Update, Delete) application using the MERN stack. The application will allow users to create, read, update, and delete tasks.

Prerequisites

To follow along with this tutorial, you should have the following software installed on your machine:

  • Node.js and npm

  • MongoDB

  • Code editor (Visual Studio Code, Sublime Text, Atom, etc.)

Step 1: Setting Up the Project

To begin, we need to create a new MERN stack project. Open your terminal and create a new directory for the project:

mkdir mern-crud

Change into the newly created directory:

cd mern-crud

Initialize the project with npm:

npm init

Follow the prompts to create a package.json file.

Next, we need to install the necessary dependencies for the project. Run the following command:

npm install express mongoose react react-dom

This command will install the following packages:

  • Express.js: A web application framework for Node.js

  • Mongoose: A MongoDB object modelling tool for Node.js

  • React: A JavaScript library for building user interfaces

  • React DOM: A package for React that provides DOM-specific methods

Step 2: Creating the Server

After installing the necessary dependencies, we can start building the server-side of our application. Create a new file called server.js in the root directory of the project:

touch server.js

Open the file in your code editor and add the following code:

const express = require('express');
const mongoose = require('mongoose');

const app = express();

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

app.listen(5000, () => {
  console.log('Server started on port 5000...');
});

This code imports the necessary packages and initializes the Express.js application. We then connect to a local MongoDB database using Mongoose. Finally, we start the server on port 5000.

Step 3: Defining the Task Model

Before we can create, read, update, or delete tasks, we need to define a task model using Mongoose. In the root directory of the project, create a new directory called models:

mkdir models

Change into the newly created directory:

cd models

Create a new file called Task.js:

touch Task.js

Open the file in your code editor and add the following code:

const mongoose = require('mongoose');

const TaskSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true,
  },
  description: {
    type: String,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model('Task', TaskSchema);

This code defines a task schema with a title, description, and createdAt field. We export the model using module.exports.

Step 4: Creating the Routes

Now that we have defined the task model, we can create the routes for creating, reading, updating, and deleting tasks. In the root directory of the project, create a new directory called routes:

mkdir routes

Change into the newly created directory:

cd routes

Create a new file called api.js:

touch api.js

Open the file in your code editor and add the following code:

const express =require('express'); const router = express.Router(); const Task = require('../models/Task');

// Create Task router.post('/task', (req, res) => { const { title, description } = req.body; const task = new Task({ title, description, });

task.save() .then(() => res.status(201).send(task)) .catch(err => res.status(400).send(err)); });

// Get All Tasks router.get('/tasks', (req, res) => { Task.find() .then(tasks => res.status(200).send(tasks)) .catch(err => res.status(400).send(err)); });

// Get Single Task router.get('/task/:id', (req, res) => { const { id } = req.params;

Task.findById(id) .then(task => res.status(200).send(task)) .catch(err => res.status(400).send(err)); });

// Update Task router.put('/task/:id', (req, res) => { const { id } = req.params;

Task.findByIdAndUpdate(id, req.body, { new: true }) .then(task => res.status(200).send(task)) .catch(err => res.status(400).send(err)); });

// Delete Task router.delete('/task/:id', (req, res) => { const { id } = req.params;

Task.findByIdAndDelete(id) .then(task => res.status(200).send(task)) .catch(err => res.status(400).send(err)); });

module.exports = router;

This code defines the routes for creating, reading, updating, and deleting tasks. We import the Task model and use Mongoose methods to perform CRUD operations on the database.

Step 5: Creating the React App

Now that we have set up the server side of our application, we can create the front end using React. In the root directory of the project, create a new directory called client:

```mkdir client```

Change into the newly created directory:

```cd client``` I

initialize a new React app using Create React App:

```npx create-react-app .```

The above command initializes a new React app in the current directory. The ```.``` at the end is important to specify the current directory as the location for the new React app. After the initialization is complete, open the ```package.json``` file in the ```client``` directory and add the following line to the scripts section:

"proxy": "http://localhost:5000"

This line tells Create React App to proxy API requests to the server-side of our application running on port 5000.

Step 6: Creating the Task Component

Next, we need to create a new component for displaying tasks. In the ```src`` ` directory of the ```client``` directory, create a new file called Task.js:

```touch src/Task.js```

Open the file in your code editor and add the following code:

import React from 'react';

const Task = ({ task }) => { return ( <div className="task"> <h3>{task.title}</h3> <p>{task.description}</p> </div> ); };

export default Task;

This code defines a functional component that takes a ```task``` object as a prop and displays the title and description of the task.

Step 7: Creating the TaskList Component

After creating the Task component, we need to create a new component for displaying a list of tasks. In the ```src``` directory of the ```client``` directory, create a new file called TaskList.js:

```touch src/TaskList.js```

Open the file in your code editor and add the following code:

import React, { useState, useEffect } from 'react';
import Task from './Task';

const TaskList = () => {
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    const fetchTasks = async () => {
      const response = await fetch('/api/tasks');
      const data = await response.json();
      setTasks(data);
    };

    fetchTasks();
  }, []);

  return (
    <div>
      <h2>Task List</h2>
      {tasks.map(task => (
        <Task key={task._id} task={task} />
      ))}
    </div>
  );
};

export default TaskList;

This code defines a functional component that fetches a list of tasks from the server-side of our application and displays them using the Task component. We use the useState hook to initialize a state variable for storing the list of tasks, and the useEffect hook to fetch the list of tasks when the component is mounted.

Step 8: Adding the TaskList Component to App.js

Now that we have created the TaskList component, we can add it to the main App.js file. Open the file in your code editor and replace the existing code with the following:

import React from 'react';
import './App.css';
import TaskList from './TaskList';

function App() {
  return (
    <div className="App">
      <TaskList />
    </div>
  );
}

export default App;

This code imports the TaskList component and renders it inside the main App component.

Step 9: Running the Application

Now that we have completed the implementation of our MERN stack application, we can test it by running the server-side and client-side of the application.

Open two terminal windows, one for the server-side and one for the client-side. In the first terminal window, navigate to the root directory of the project and run the following command to start the server:

npm start

In the second terminal window, navigate to the client directory and run the following command to start the client-side:

npm start

After both the server-side and client-side are running, open your web browser and navigate to http://localhost:3000. You should see a list of tasks displayed on the page.

Congratulations, you have successfully created a MERN stack application! You can now modify the code to add new features or customize the application to fit your specific needs.