Open In App

Build a Notes App with Next.js

Last Updated : 01 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Note-taking App is a simple web application that allows users to create, edit, and delete text notes. The app provides a user-friendly interface for managing notes, making it easy to add new notes, update existing notes, and delete notes when they are no longer needed. The app provides a way for users who need a quick and convenient way to write down notes and keep track of important information. In this article, we will be building a note-taking app using NextJS.

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

Screenshot-(492)

Prerequisites:

Approach to Build a Note-Taking App with Next JS:

  • Setup the Project by Creating a new Next JS project and installing required dependencies.
  • Create functional components such as NoteList and Note. These components will be responsible for displaying form for adding/editing notes and displaying individual notes respectively.
  • We will be utilizing React Hook(useState) for state management.
  • Implement functionality to delete and edit an existing note.
  • We will use Bootstrap to style the application.

Steps to create a Note-Taking App:

Step 1: Create a application of NextJS using the following command.

npx create-next-app note-taker

Step 2: Navigate to project directory

cd note-taker

Step 3: Install the necessary packages in your project using the following command.

npm install bootstrap
npm install react-icons --save

Project Structure:

Screenshot-(494)

The updated dependencies in package.json file will look like:

"dependencies": {
"bootstrap": "^5.3.3",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18",
"react-icons": "^5.0.1"
}

Example: Below are the components which describes the basic implementation of the Note-Taking App.

Javascript




// page.js
 
'use client'
import React, { useState } from 'react';
import NoteList from '../components/NoteList';
import 'bootstrap/dist/css/bootstrap.min.css';
const IndexPage = () => {
    const [notes, setNotes] = useState([
        {
            id: 1, title: 'meeting',
            description: 'Review project, assign task',
            important: false
        },
        {
            id: 2, title: 'Grocery',
            description: 'Milk, Sugar, Apples, eggs',
            important: false
        },
    ]);
 
    const deleteNote = (id) => {
        setNotes(notes.filter((note) => note.id !== id));
    };
 
 
    return (
        <div className="container col-md-9 mb-3
             mt-5 bg-light border border-dark">
            <div class="col text-center">
                <h2 className='text-success mt-3'>
                    GeekForGeeks
                </h2>
                <h4>Note Taking App</h4>
            </div>
            <NoteList notes={notes}
                setNotes={setNotes} onDelete={deleteNote} />
        </div>
    );
};
 
export default IndexPage;


Javascript




// NoteList.js
 
import React, { useState } from 'react';
import Note from './Note';
import 'bootstrap/dist/css/bootstrap.min.css';
 
const NoteList = ({ notes, setNotes, onDelete }) => {
    const [newTitle, setNewTitle] = useState('');
    const [newDescription, setNewDescription] = useState('');
    const [newImportant, setNewImportant] = useState(false);
    const [editingNoteId, setEditingNoteId] = useState(null);
 
    const handleAddNote = () => {
        const newNote = {
            id: notes.length + 1,
            title: newTitle,
            description: newDescription,
            important: newImportant,
        };
        setNotes([...notes, newNote]);
        setNewTitle('');
        setNewDescription('');
        setNewImportant(false);
    };
 
    const onMarkImportant = (id) => {
        setNotes(
            notes.map((note) =>
                note.id === id ? {
                    ...note,
                    important: !note.important
                } : note
            )
        );
    };
 
    const handleUpdateNote = (id, updatedTitle,
        updatedDescription, updatedImportant) => {
        const updatedNotes = notes.map((note) =>
            note.id === id ? {
                ...note,
                title: updatedTitle,
                description: updatedDescription,
                important: updatedImportant
            }
                : note
        );
        setNotes(updatedNotes);
        setEditingNoteId(null);
        setNewTitle('');
        setNewDescription('');
        setNewImportant(false);
    };
 
    return (
        <div className='container '>
            <div className="row mb-3">
                <div className="col">
                    <input
                        type="text"
                        className="form-control"
                        placeholder="Note Title"
                        value={newTitle}
                        onChange={(e) => setNewTitle(e.target.value)}
                    />
                </div>
                <div className="col">
                    <input
                        type="text"
                        className="form-control"
                        placeholder="Note Description"
                        value={newDescription}
                        onChange={(e) => setNewDescription(e.target.value)}
                    />
                </div>
 
            </div>
            <div className="row mb-3">
                <div className="col">
                    <div className="form-check">
                        <input
                            type="checkbox"
                            className="form-check-input"
                            id="importantCheck"
                            checked={newImportant}
                            onChange={(e) => setNewImportant(e.target.checked)}
                        />
                        <label className="form-check-label"
                            htmlFor="importantCheck">
                            Mark as Important
                        </label>
                    </div>
                </div>
                <div className="col">
                    {editingNoteId ? (
                        <button
                            className="btn btn-success"
                            onClick={() => handleUpdateNote(
                                editingNoteId,
                                newTitle,
                                newDescription,
                                newImportant)}
                        >
                            Save
                        </button>
                    ) : (
                        <button className="btn btn-primary"
                            onClick={handleAddNote}>
                            Add Note
                        </button>
                    )}
                </div>
            </div>
            <div className="row">
                {notes.map((note) => (
                    <div key={note.id} className="col-md-4 mb-3">
                        <Note
                            note={note}
                            onMarkImportant={onMarkImportant}
                            onDelete={onDelete}
                            onEdit={() => {
                                setNewTitle(note.title);
                                setNewDescription(note.description);
                                setNewImportant(note.important);
                                setEditingNoteId(note.id);
                            }}
                        />
                    </div>
                ))}
            </div>
        </div>
    );
};
 
export default NoteList;


Javascript




// Note.js
 
import { FaTrash, FaEdit, FaStar } from 'react-icons/fa';
import 'bootstrap/dist/css/bootstrap.min.css';
 
const Note = ({ note, onDelete, onEdit, onMarkImportant }) => {
    const { id, title, description, important } = note;
 
    return (
        <div className={`card ${important ? 'border-dark' : 'border-dark'}
                         mb-3`} style={{ maxWidth: '18rem' }}>
            <div className="card-body d-flex justify-content-between
                            align-items-center">
                <div>
                    <FaStar className={`me-2
           ${important ? 'text-warning' : 'text-secondary'} `}
                        onClick={() => onMarkImportant(id)} />
                    <h5 className="card-title">{title}</h5>
                    <p className="card-text">{description}</p>
                </div>
                <div>
                    <button className="btn me-2 text-danger"
                        onClick={() => onDelete(id)}
                        style={{ backgroundColor: 'none', fontSize: '1rem' }}>
                        <FaTrash style={{ fontSize: '1rem' }} />
                    </button>
                    <button className="btn text-primary"
                        onClick={() => onEdit(id)}
                        style={{ backgroundColor: 'none' }}>
                        <FaEdit style={{ fontSize: '1rem' }} />
                    </button>
                </div>
            </div>
        </div>
    );
};
 
export default Note;


Start your application using the following command.

npm run dev

Output: Naviagate to the URL http://localhost:3000.

gfg_note_maker



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

Similar Reads