Lecture Notes Of Day 29MongoDB with React.js
1. Introduction
to Full-Stack Development
A full-stack web application
includes both the frontend (user interface) and the backend
(server, database). In this lesson, we are going to create a full-stack
application using MongoDB, Express.js, and React.js,
commonly known as the MERN stack.
- Frontend:
React.js will be used to create the user interface.
- Backend:
Express.js will serve as the backend framework to handle HTTP requests.
- Database:
MongoDB will store and manage the data for our application.
2. Setting
Up the Project
To get started, let's set up both
the frontend and backend of the application.
2.1 Setting
Up the Backend (Express.js and MongoDB)
1. Install
Node.js: Make sure you have Node.js installed on your computer. You can
download it from Node.js official
website.
2. Create a
New Directory: Create a folder for your project and navigate to
it in your terminal.
mkdir mern-stack-app
cd
mern-stack-app
3. Initialize npm: Initialize a new Node.js project by running the following command.
npm init
-y
4. Install
Required Packages: Install Express, Mongoose (MongoDB
ODM), and Cors (to handle cross-origin requests) using the following
command.
npm install express mongoose cors
5. Create
Backend Files: Inside your project folder, create the following
files:
o
server.js: This will set up the Express
server and connect to MongoDB.
o
models/User.js: This will define the schema for
storing user data in MongoDB.
o
routes/userRoutes.js: This
will define routes for the user operations (CRUD).
6. Connecting to MongoDB: In the server.js file, set up the connection to MongoDB.
const
express = require('express');
const
mongoose = require('mongoose');
const
cors = require('cors');
const app
= express();
app.use(cors());
app.use(express.json());
// to parse JSON data
mongoose.connect('mongodb://localhost:27017/mern-stack', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to
MongoDB'))
.catch(err => console.log('Failed to connect to MongoDB', err));
const PORT
= process.env.PORT || 5000;
app.listen(PORT,
() => {
console.log(`Server running on port ${PORT}`);
});
7. Creating
a User Model: Define the User schema in models/User.js.
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique:
true },
password: { type: String, required: true }
});
module.exports = mongoose.model('User', userSchema);
8. Setting
Up Routes: In routes/userRoutes.js, create routes for creating and
fetching users.
const express = require('express');
const router
= express.Router();
const User = require('../models/User');
// POST
route for creating a new user
router.post('/users',
async (req, res) => {
const { name, email, password } = req.body;
const newUser = new User({ name, email, password });
try {
await newUser.save();
res.status(201).json(newUser);
} catch (error) {
res.status(400).json({ message: error.message
});
}
});
// GET
route for fetching all users
router.get('/users',
async (req, res) => {
try {
const users = await User.find();
res.json(users);
} catch (error) {
res.status(400).json({ message: error.message
});
}
});
module.exports
= router;
9. Mounting
Routes: Finally, in server.js, import and mount the routes.
const userRoutes = require('./routes/userRoutes');
app.use('/api',
userRoutes);
2.2 Setting
Up the Frontend (React.js)
1. Create
React App: In the root directory of your project, create a new React app using
the following command.
npx create-react-app client
cd client
2. Install
Axios: Install Axios for making HTTP requests from React to the backend.
npm install axios
3. Create a
User Component: Inside the src folder of the React app,
create a new file called User.js to handle user-related actions like
displaying users and adding new ones.
Example of displaying users in User.js:
import React, { useEffect, useState } from 'react';
import
axios from 'axios';
const User = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/api/users')
.then(response => {
setUsers(response.data);
})
.catch(error => {
console.error('There was an error
fetching the users!', error);
});
}, []);
return (
<div>
<h1>User List</h1>
<ul>
{users.map(user => (
<li key={user._id}>{user.name}
- {user.email}</li>
))}
</ul>
</div>
);
};
export default User;
4. Running
the Backend and Frontend:
o
Start the backend by running:
node server.js
o Start the frontend by navigating to the client folder and running:
npm start
5. Now, you
should be able to access your React app on http://localhost:3000 and
interact with the data coming from MongoDB via Express.js.
3. Testing
the Application
1. Test
Backend: Use Postman or your browser to test the backend:
o
Create a user: POST http://localhost:5000/api/users
with JSON body:
{
"name": "John Doe",
"email": "john.doe@example.com",
"password": "password123"
}
o
Fetch all users: GET
http://localhost:5000/api/users.
2. Test
Frontend: Ensure the user list is displayed on the React application. Any new
user added through the backend should appear in the frontend.
4. Conclusion
By the end of this lesson,
students will have a working full-stack web application that connects a React.js
frontend with a MongoDB backend via Express.js. Students
should be able to:
- Set
up a MongoDB database.
- Create
and use models with Mongoose in the backend.
- Send
and receive data between the frontend (React.js) and backend (Express.js)
using Axios.
- Handle
basic CRUD operations in a full-stack application.
5. Homework/Practice
1. Add the
ability to delete users from the list on both the backend and frontend.
2. Implement
user authentication (login/signup) and store the user's session using cookies
or JWT.
3. Create a
form to add new users from the React frontend and connect it to the backend.
SOLUTION:
1. Delete Users from the List (Backend and Frontend)
1.1 Backend
- Add a Route to Delete Users
In the backend (routes/userRoutes.js), add a new route to handle the deletion of a user by their ID.
// DELETE
route for deleting a user by ID
router.delete('/users/:id',
async (req, res) => {
try {
const deletedUser = await User.findByIdAndDelete(req.params.id);
if (!deletedUser) {
return res.status(404).json({ message: 'User
not found' });
}
res.status(200).json({ message: 'User
deleted successfully' });
} catch (error) {
res.status(400).json({ message: error.message
});
}
});
1.2 Frontend
- Add a Delete Button and Handle Deletion
In User.js (frontend), add a button to delete users. Modify the component to send a DELETE request to the backend.
import React,
{ useEffect, useState } from 'react';
import axios from 'axios';
const User
= () => {
const [users, setUsers] = useState([]);
axios.get('http://localhost:5000/api/users')
.then(response => {
setUsers(response.data);
})
.catch(error => {
console.error('There was an error
fetching the users!', error);
});
}, []);
try {
await axios.delete(`http://localhost:5000/api/users/${userId}`);
setUsers(users.filter(user => user._id
!== userId));
} catch (error) {
console.error('There was an error
deleting the user!', error);
}
};
<div>
<h1>User List</h1>
<ul>
{users.map(user => (
<li key={user._id}>
{user.name} - {user.email}
<button onClick={() =>
deleteUser(user._id)}>Delete</button>
</li>
))}
</ul>
</div>
);
};
export default User;
Now, when you click the
"Delete" button, the user will be deleted from both the frontend and
the backend.
2. User
Authentication (Login/Signup) with JWT
2.1 Backend
- User Authentication (JWT Setup)
Install jsonwebtoken and bcryptjs to handle user authentication:
npm
install jsonwebtoken bcryptjs
2.2 Create
JWT Authentication Logic
In server.js, add the following code for generating JWT tokens upon user login:
const
bcrypt = require('bcryptjs');
const jwt
= require('jsonwebtoken');
const User = require('./models/User');
// POST
route for user signup
router.post('/signup',
async (req, res) => {
const { name, email, password } = req.body;
const hashedPassword = await bcrypt.hash(password,
10);
try {
await newUser.save();
res.status(201).json({ message: 'User
created successfully' });
} catch (error) {
res.status(400).json({ message: error.message
});
}
});
router.post('/login',
async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
return res.status(400).json({ message: 'Invalid
credentials' });
}
if (!isMatch) {
return res.status(400).json({ message: 'Invalid
credentials' });
}
res.json({ token });
});
2.3 Frontend
- Implement Signup and Login Forms
Create two forms: one for signing
up and one for logging in.
Signup Form (Signup.js):
import React, { useState } from 'react';
import axios from 'axios';
const Signup
= () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
e.preventDefault();
const user = { name, email, password };
await axios.post('http://localhost:5000/api/signup',
user);
alert('Signup successful!');
} catch (error) {
console.error('There was an error signing
up!', error);
}
};
<form onSubmit={handleSubmit}>
<input type="text" value={name}
onChange={(e) => setName(e.target.value)} placeholder="Name"
required />
<input type="email" value={email}
onChange={(e) => setEmail(e.target.value)} placeholder="Email"
required />
<input type="password" value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password" required />
<button type="submit">Sign
Up</button>
</form>
);
};
Login Form (Login.js):
import React, { useState } from 'react';
import
axios from 'axios';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [token, setToken] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
const user = { email, password };
try {
const response = await axios.post('http://localhost:5000/api/login',
user);
setToken(response.data.token);
alert('Login successful!');
} catch (error) {
console.error('There was an error logging
in!', error);
}
};
return (
<form onSubmit={handleSubmit}>
<input type="email" value={email}
onChange={(e) => setEmail(e.target.value)} placeholder="Email"
required />
<input type="password" value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password" required />
<button type="submit">Login</button>
</form>
);
};
export default Login;
Once logged in, you can store the
JWT in the browser's localStorage or cookies for subsequent requests to secure
routes.
3. Create
a Form to Add New Users from React Frontend
Create a form to submit new users to the backend.
import React,
{ useState } from 'react';
import
axios from 'axios';
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
e.preventDefault();
const newUser = { name, email, password };
await axios.post('http://localhost:5000/api/users',
newUser);
alert('User added successfully!');
} catch (error) {
console.error('There was an error adding
the user!', error);
}
};
<form onSubmit={handleSubmit}>
<input type="text" value={name}
onChange={(e) => setName(e.target.value)} placeholder="Name"
required />
<input type="email" value={email}
onChange={(e) => setEmail(e.target.value)} placeholder="Email"
required />
<input
type="password" value={password} onChange={(e) =>
setPassword(e.target.value)} placeholder="Password" required />
<button type="submit">Add
User</button>
</form>
);
};
Conclusion
With the solutions above, you:
- Added
functionality to delete users both in the frontend and backend.
- Implemented
user authentication (signup and login) using JWT for
securing routes.
- Created
a form to add new users from the React frontend to the MongoDB
backend.
