DEV Community

Cover image for Connect a React App with MongoDB using Node.js and Express.js
Sudhanshu Gaikwad
Sudhanshu Gaikwad

Posted on

3

Connect a React App with MongoDB using Node.js and Express.js

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

Enter fullscreen mode Exit fullscreen mode

Setup the Backend with Node.js, Express & MongoDB

mkdir backend
cd backend
npm init -y
npm install express mongoose cors dotenv

Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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;


Enter fullscreen mode Exit fullscreen mode

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}`));

Enter fullscreen mode Exit fullscreen mode

Setup Frontend with React

npx create-react-app frontend
cd frontend
npm install axios

Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

Final Steps

Run backend:

node server.js

Enter fullscreen mode Exit fullscreen mode

Run frontend:

npm start

Enter fullscreen mode Exit fullscreen mode

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.

Developer-first embedded dashboards

Developer-first embedded dashboards

Embed in minutes, load in milliseconds, extend infinitely. Import any chart, connect to any database, embed anywhere. Scale elegantly, monitor effortlessly, CI/CD & version control.

Get early access

Top comments (0)

For IaC Practitioners, By IaC Practitioners

For IaC Practitioners, By IaC Practitioners

Learn how to embed security from day one using policy-as-code, AI-driven scanning, and strong collaboration between engineering and cybersecurity teams at IaCConf on Wednesday August 27, 2025.

Join us on August 27

👋 Kindness is contagious

Explore this practical breakdown on DEV’s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple “thank you” or question in the comments goes a long way in supporting authors—your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay