Open In App

Notes Maker App using MERN Stack

Last Updated : 14 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

The “Notes Maker” project is an helpful web application designed to help users effectively create, manage, and organize their notes. In this article we are utilizing the MERN (MongoDB, Express, React, Node) Stack, to build a notes maker application that provides a seamless user experience for note-taking.

Preview of final output: Let us have a look at how the final application will look like.

sdafsghjkl

Project preview

Prerequisites

Approach to create Notes Maker App:

  • The Notes Maker project is approached with a structured methodology, dividing responsibilities into stateful backend controllers and stateless frontend components.
  • On the backend, Express.js connects to MongoDB Atlas, with server.js acting as the controller for CRUD operations.
  • The frontend uses React.js, where App.js manages overall state and communication with the backend, while stateless components like AddNote.js and NoteList.js handle UI elements.
  • A minimal directory structure ensures clarity, and CSS styling enhances the user interface.

Functionalities of Notes Maker App:

The project employs a backend built with Node.js and Express.js, utilizing MongoDB as the database for note storage. On the front end, React.js is employed to create an interactive user interface. The functionalities include:

  • Adding new notes with titles and content.
  • Displaying a list of existing notes.
  • Update/Delete Notes.

Steps to Create the Project:

Step 1: Create a new directory for your project and navigate to it using the terminal.

mkdir notes-maker
cd notes-maker

Step 2: Create a server directory for your backend and navigate into it.

mkdir server
cd server

Step 3: Initialize a new Node.js project for the backend.

npm init -y

Step 4: Install the necessary backend dependencies.

npm install express mongoose cors body-parser

Project Structure (Backend):

11111

Dependencies (Backend):

"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"mongoose": "^8.0.3"
}

Step 5: Create a server.js file inside the server directory and add the following code:

Javascript




//server.js
 
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const bodyParser = require("body-parser");
 
const app = express();
const PORT = process.env.PORT || 5000;
 
// Middleware
app.use(cors());
app.use(bodyParser.json());
 
// Connect to MongoDB Atlas
const dbURI = "your mongodb connection string";
mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true });
 
// Define Note model
const Note = mongoose.model("Note", {
    title: String,
    content: String,
});
 
// Listen for successful MongoDB connection
mongoose.connection.on("connected", () => {
    console.log("Connected to MongoDB Atlas");
});
 
// Listen for MongoDB connection errors
mongoose.connection.on("error", (err) => {
    console.error("MongoDB connection error:", err);
});
 
// Routes
app.get("/", (req, res) => {
    res.send("Hello, this is the root!");
});
 
app.get("/api/notes", async (req, res) => {
    try {
        const notes = await Note.find();
        res.json(notes);
    } catch (error) {
        res.status(500).json({ message: error.message });
    }
});
 
// Update Note by ID
// Update Note by ID
app.put("/api/notes/:id", async (req, res) => {
    const { title, content } = req.body;
    const noteId = req.params.id;
 
    try {
        const updatedNote = await Note.findByIdAndUpdate(
            noteId,
            { title, content },
            { new: true }
        );
        res.json(updatedNote);
    } catch (error) {
        res.status(404).json({ message: "Note not found" });
    }
});
 
// Delete Note by ID
app.delete("/api/notes/:id", async (req, res) => {
    const noteId = req.params.id;
 
    try {
        await Note.findByIdAndDelete(noteId);
        res.json({ message: "Note deleted successfully" });
    } catch (error) {
        res.status(404).json({ message: "Note not found" });
    }
});
 
app.post("/api/notes", async (req, res) => {
    const { title, content } = req.body;
 
    const note = new Note({ title, content });
 
    try {
        const newNote = await note.save();
        res.status(201).json(newNote);
    } catch (error) {
        res.status(400).json({ message: error.message });
    }
});
 
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});


To run the backend server run the following command.

node server.js

Step 6: Navigate to the root directory. Run the following command to initialize a new React app:

npx create-react-app client
cd client

Step 7: Install the required dependencies.

npm i axios

Folder Structure(Frontend):

directory

Dependencies(Frontend):

"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.6.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

Example: Add the given code in the respective files.

Javascript




//App.js
 
import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import NoteList from "./components/NoteList";
import AddNote from "./components/AddNote";
 
const App = () => {
    const [notes, setNotes] = useState([]);
    const [title, setTitle] = useState("");
    const [content, setContent] = useState("");
 
    useEffect(() => {
        // Fetch notes from the server
        axios
            .get("http://localhost:5000/api/notes")
            .then((response) => setNotes(response.data))
            .catch((error) => console.error("Error fetching notes:", error));
    }, []);
 
    const handleAddNote = () => {
        // Add a new note to the server
        axios
            .post("http://localhost:5000/api/notes", { title, content })
            .then((response) => {
                setNotes([...notes, response.data]);
                setTitle("");
                setContent("");
            })
            .catch((error) => console.error("Error adding note:", error));
    };
    const handleEditNote = (id, updatedTitle, updatedContent) => {
        // Update note by ID
        axios
            .put(`http://localhost:5000/api/notes/${id}`, {
                title: updatedTitle,
                content: updatedContent,
            })
            .then((response) => {
                const updatedNotes = notes.map((note) =>
                    note._id === id ? response.data : note
                );
                setNotes(updatedNotes);
            })
            .catch((error) => console.error("Error updating note:", error));
    };
 
    const handleDeleteNote = (id) => {
        // Delete note by ID
        axios
            .delete(`http://localhost:5000/api/notes/${id}`)
            .then((response) => {
                const updatedNotes = notes.filter((note) => note._id !== id);
                setNotes(updatedNotes);
            })
            .catch((error) => console.error("Error deleting note:", error));
    };
 
    return (
        <div className="app-container">
            <h1>Notes App</h1>
            <AddNote
                title={title}
                setTitle={setTitle}
                content={content}
                setContent={setContent}
                onAddNote={handleAddNote}
            />
            <NoteList
                notes={notes}
                onEditNote={handleEditNote}
                onDeleteNote={handleDeleteNote}
            />
        </div>
    );
};
 
export default App;


Javascript




// components/NoteList.js
 
import React from "react";
 
const NoteList = ({ notes, onEditNote, onDeleteNote }) => {
    return (
        <ul>
            {notes.map((note) => (
                <li key={note._id}>
                    <strong>{note.title}</strong>
                    <p>{note.content}</p>
 
                    <button
                        className="button2"
                        style={{ marginRight: "15px" }}
                        onClick={() =>
                            onEditNote(
                                note._id,
                                prompt("Enter updated title:", note.title),
                                prompt("Enter updated content:", note.content)
                            )
                        }
                    >
                        Edit
                    </button>
                    <button
                        className="button2"
                        onClick={() => onDeleteNote(note._id)}
                    >
                        Delete
                    </button>
                </li>
            ))}
        </ul>
    );
};
 
export default NoteList;


Javascript




//componenets/AddNode.js
 
import React from "react";
 
const AddNote = ({ title, setTitle, content, setContent, onAddNote }) => {
    return (
        <div>
            <h2>Add Note</h2>
            <input
                type="text"
                placeholder="Title"
                value={title}
                onChange={(e) => setTitle(e.target.value)}
            />
            <textarea
                placeholder="Content"
                value={content}
                onChange={(e) => setContent(e.target.value)}
            ></textarea>
            <button className="button1" onClick={onAddNote}>
                Add Note
            </button>
        </div>
    );
};
 
export default AddNote;


CSS




/* App.css */
 
body {
    font-family: 'Arial', sans-serif;
    background-color: #f4f4f4;
    margin: 0;
    padding: 0;
}
 
.app-container {
    max-width: 800px;
    margin: 20px auto;
    padding: 20px;
    background-color: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    border-radius: 5px;
}
 
h1 {
    color: #333;
}
 
form {
    display: flex;
    flex-direction: column;
}
 
label {
    margin-bottom: 8px;
    font-size: 16px;
}
 
input {
    margin-bottom: 15px;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-sizing: border-box;
    width: 100%;
}
 
.button1,
.button2 {
    margin-bottom: 15px;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-sizing: border-box;
}
 
.button1 {
    width: 100%;
}
 
.button2 {
    width: 49%;
 
}
 
textarea {
    margin-bottom: 15px;
    padding: 10px;
    font-size: 16px;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-sizing: border-box;
    resize: vertical;
    height: 100px;
    width: 100%;
}
 
button {
    background-color: #4caf50;
    color: #fff;
    cursor: pointer;
}
 
button:hover {
    background-color: #45a049;
}
 
ul {
    list-style-type: none;
    padding: 0;
}
 
li {
    margin-bottom: 15px;
    padding: 10px;
    background-color: #eee;
    border-radius: 5px;
}
 
li strong {
    font-size: 18px;
    color: #333;
}
 
li p {
    font-size: 16px;
    color: #555;
}


To run the application,type the following command:

node server.js

Output:

Animation24

Final Output



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads