Unlock the full potential of the MERN stack with this complete, beginner-to-pro guide! In this hands-on tutorial, you'll learn how to seamlessly connect your React.js frontend to a MongoDB database using Node.js and Express.js in 2025. We cover everything step-by-stepβfrom setting up the backend server and creating RESTful APIs to integrating them into your React application.
π Folder Structure
project-root/ β βββ backend/ β βββ config/ β β βββ db.js β βββ models/ β β βββ Note.js β βββ routes/ β β βββ notes.js β βββ server.js β βββ frontend/ β βββ src/ β β βββ components/ β β βββ App.js
Setup the Backend with Node.js, Express & MongoDB
mkdir backend cd backend npm init -y npm install express mongoose cors dotenv
Create MongoDB Connection File (config/db.js
)
const mongoose = require("mongoose"); const connectDB = async (url) => { try { await mongoose.connect(url); // β
Clean usage console.log("β
MongoDB Connected"); } catch (error) { console.error("β MongoDB connection error:", error.message); process.exit(1); } }; module.exports = connectDB;
Define a Mongoose Model (models/Note.js
)
const express = require("express"); const router = express.Router(); const Note = require("../models/Note"); router.get("/", async (req, res) => { const notes = await Note.find(); res.json(notes); }); router.post("/", async (req, res) => { const note = new Note(req.body); await note.save(); res.status(201).json(note); }); module.exports = router;
Create API Routes (routes/notes.js
)
const express = require("express"); const router = express.Router(); const Note = require("../models/Note"); router.get("/", async (req, res) => { const notes = await Note.find(); res.json(notes); }); router.post("/", async (req, res) => { const note = new Note(req.body); await note.save(); res.status(201).json(note); }); module.exports = router;
Create server.js (Entry Point)
const express = require("express"); const cors = require("cors"); const dotenv = require("dotenv"); // β
Required for env support const connectDB = require("./config/db"); const notesRoutes = require("./routes/notes"); dotenv.config(); // β
Load .env variables const app = express(); const connection_url = "Enter your URL"; // β
Pass your connection URL to the connectDB function connectDB(connection_url); app.use(cors()); app.use(express.json()); app.use("/api/notes", notesRoutes); const PORT = process.env.PORT || 5000; app.listen(PORT, () => console.log(`π Server running on port ${PORT}`));
Setup Frontend with React
npx create-react-app frontend cd frontend npm install axios
Connect Frontend to Backend
import React, { useEffect, useState } from "react"; import axios from "axios"; import styled from "styled-components"; import { FaEdit, FaTrash } from "react-icons/fa"; // React Icons // Styled Components const Container = styled.div` max-width: 800px; margin: auto; padding: 1rem; font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; color: #fff; /* background: linear-gradient(145deg, #0d0d0d, #1a1a1a); */ min-height: 100vh; `; const Title = styled.h1` text-align: center; color: #00aaff; `; const Form = styled.div` display: flex; flex-direction: column; gap: 1rem; margin-bottom: 2rem; `; const Input = styled.input` padding: 0.75rem; font-size: 1rem; border: none; border-radius: 8px; background: transparent; border: 1px solid #353535; color: white; &:focus { border-color: #3f51ff; outline: none; } `; const TextArea = styled.textarea` padding: 0.75rem; font-size: 1rem; border: none; border-radius: 8px; background: transparent; border: 1px solid #353535; color: white; resize: vertical; &:focus { border-color: #3f51ff; outline: none; } `; const Button = styled.button` padding: 0.75rem; font-size: 1rem; background: #194bfd; background: linear-gradient( 90deg, rgba(25, 75, 253, 1) 0%, rgba(173, 19, 251, 1) 100% ); transition: all 0.3s ease; color: #ffffff; border: none; border-radius: 8px; cursor: pointer; &:hover { background-color: #5a189a; box-shadow: 0 6px 16px rgba(90, 24, 154, 0.5); color: #ffffff; transform: translateY(-2px); } `; const NoteGrid = styled.div` display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; `; const NoteCard = styled.div` background: #1e1e1e; border-radius: 12px; padding: 1.5rem; position: relative; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); h3 { margin-top: 0; color: #00aaff; } p { color: #ccc; } .actions { margin-top: 1rem; display: flex; gap: 0.5rem; button { flex: 1; padding: 0.5rem; border: none; border-radius: 6px; cursor: pointer; font-weight: 500; display: flex; align-items: center; justify-content: center; gap: 5px; } .edit { background-color: #ffaa00; color: #121212; &:hover { background-color: #e69a00; } } .delete { background-color: #ff4d4d; color: white; &:hover { background-color: #e04343; } } } `; function App() { const [notes, setNotes] = useState([]); const [form, setForm] = useState({ title: "", content: "" }); const [editingId, setEditingId] = useState(null); const fetchNotes = async () => { const res = await axios.get("http://localhost:5000/api/notes"); setNotes(res.data); }; const addOrUpdateNote = async () => { if (editingId) { await axios.put(`http://localhost:5000/api/notes/${editingId}`, form); setEditingId(null); } else { await axios.post("http://localhost:5000/api/notes", form); } fetchNotes(); setForm({ title: "", content: "" }); }; const deleteNote = async (id) => { await axios.delete(`http://localhost:5000/api/notes/${id}`); fetchNotes(); }; const editNote = (note) => { setForm({ title: note.title, content: note.content }); setEditingId(note._id); }; useEffect(() => { fetchNotes(); }, []); return ( <Container> <Title>π Notes App</Title> <Form> <Input type="text" placeholder="Title" value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} /> <TextArea placeholder="Content" rows={4} value={form.content} onChange={(e) => setForm({ ...form, content: e.target.value })} /> <Button onClick={addOrUpdateNote}> {editingId ? "Update Note" : "Add Note"} </Button> </Form> <h2 style={{ color: "#ccc" }}>All Notes</h2> <NoteGrid> {notes.map((note) => ( <NoteCard key={note._id}> <h3>{note.title}</h3> <p>{note.content}</p> <div className="actions"> <button className="edit" onClick={() => editNote(note)}> <FaEdit /> Edit </button> <button className="delete" onClick={() => deleteNote(note._id)}> <FaTrash /> Delete </button> </div> </NoteCard> ))} </NoteGrid> </Container> ); } export default App;
Final Steps
Run backend:
node server.js
Run frontend:
npm start
Deploying to the Internet
- Use Render or Railway for backend deployment
- Use Vercel or Netlify for frontend deployment
- Connect via environment variables and update frontend API URL
Conclusion
Congratulations! You've successfully built a full-stack MERN application by connecting a React frontend to a MongoDB database using Node.js and Express. From setting up the server and creating RESTful APIs to integrating them into your React componentsβyou've now covered all the essential steps needed to master the foundational flow of full-stack development.
Top comments (0)