DEV Community

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

Posted on

2

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

Image description

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

Image description

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.

Sentry image

Make it make sense

Make sense of fixing your code with straight-forward application monitoring.

Start debugging β†’

Top comments (0)

Build gen AI apps that run anywhere with MongoDB Atlas

Build gen AI apps that run anywhere with MongoDB Atlas

MongoDB Atlas bundles vector search and a flexible document model so developers can build, scale, and run gen AI apps without juggling multiple databases. From LLM to semantic search, Atlas streamlines AI architecture. Start free today.

Start Free

Join the Algolia MCP Server Challenge: $3,000 in Prizes!

Explore the intersection of AI and search technology by building with the Algolia’s MCP Server. Three talented winners will be selected to share in our $3,000 prize pool!

Check out the challenge

DEV is bringing live events to the community. Dismiss if you're not interested. ❀️