Node Express Part3

by Kuligaposten 2026-02-16

A guide in Node Express backend.

Part 3: Connecting Express + MongoDB API to a React Frontend

By the end of this guide, you’ll have a React app that can create, read, update, and delete users via the Express API you built in Part 2.


1. Prerequisites

  • Node.js + npm (or yarn)
  • Your Express + MongoDB API running locally (npm run dev)
  • Basic React knowledge (optional, but helpful)

2. Create a React App

Use Vite or Create React App. I’ll use Vite for speed:

npm create vite@latest my-react-app
# Choose React + JavaScript
cd my-react-app
npm install
npm run dev

Your React app will now be running at http://localhost:5173 (or similar).


3. Install Axios

We’ll use Axios to make HTTP requests:

npm install axios

4. Create a Service for API Calls

In src/services/api.js:

import axios from "axios";

const API_URL = "http://localhost:3000/api/users";

export const getUsers = () => axios.get(API_URL);
export const getUser = (id) => axios.get(`${API_URL}/${id}`);
export const createUser = (data) => axios.post(API_URL, data);
export const updateUser = (id, data) => axios.put(`${API_URL}/${id}`, data);
export const deleteUser = (id) => axios.delete(`${API_URL}/${id}`);

5. Build a Simple Users Component

Create src/components/Users.jsx:

import React, { useState, useEffect } from "react";
import { getUsers, createUser, updateUser, deleteUser } from "../services/api";

export default function Users() {
  const [users, setUsers] = useState([]);
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");

  // Fetch users on load
  useEffect(() => {
    fetchUsers();
  }, []);

  const fetchUsers = async () => {
    try {
      const response = await getUsers();
      setUsers(response.data);
    } catch (err) {
      console.error(err);
    }
  };

  const handleAddUser = async () => {
    if (!name || !email) return;
    try {
      await createUser({ name, email });
      setName("");
      setEmail("");
      fetchUsers();
    } catch (err) {
      console.error(err);
    }
  };

  const handleDeleteUser = async (id) => {
    try {
      await deleteUser(id);
      fetchUsers();
    } catch (err) {
      console.error(err);
    }
  };

  return (
    <div>
      <h2>Users</h2>
      <div>
        <input
          placeholder="Name"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
        <input
          placeholder="Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <button onClick={handleAddUser}>Add User</button>
      </div>
      <ul>
        {users.map((user) => (
          <li key={user._id}>
            {user.name} ({user.email})
            <button onClick={() => handleDeleteUser(user._id)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

6. Render Users Component in App

Update src/App.jsx:

import React from "react";
import Users from "./components/Users";

function App() {
  return (
    <div className="App">
      <h1>My Full-Stack App</h1>
      <Users />
    </div>
  );
}

export default App;

7. CORS Setup

Since React runs on a different port than Express, enable CORS in your API:

npm install cors

In index.js of your Express app:

const cors = require("cors");
app.use(cors());

Now your React frontend can make requests to your API without issues.


8. Optional: Edit Users

You can expand your app with an edit feature. For example, add handleEditUser in the Users.jsx component:

const handleEditUser = async (id) => {
  const newName = prompt("Enter new name:");
  const newEmail = prompt("Enter new email:");
  if (!newName || !newEmail) return;
  try {
    await updateUser(id, { name: newName, email: newEmail });
    fetchUsers();
  } catch (err) {
    console.error(err);
  }
};

And add a button:

<button onClick={() => handleEditUser(user._id)}>Edit</button>

9. Final Structure

Your project structure may look like:

my-react-app/
│
├── src/
│   ├── components/
│   │   └── Users.jsx
│   ├── services/
│   │   └── api.js
│   └── App.jsx
├── package.json
└── vite.config.js

Conclusion

You now have a full-stack application:

  1. Backend: Node.js + Express + MongoDB API
  2. Frontend: React app with CRUD functionality
  3. Communication: Axios requests over HTTP with CORS enabled

From here, you can:

  • Add better styling (Tailwind, Material UI, etc.)
  • Implement authentication (JWT or OAuth)
  • Deploy your app to Vercel/Netlify (frontend) and Render/Heroku (backend)
Back to Home