Unable to resolve the errors. All the method are set correctly but still gettng the error of "Cannot POST" AND Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON. Cannot find the issue in my POST or GET requests neither on server side nor on client side. Please suggest a solution by reviewing the following code?
Also Note: Error is causing an issue to login/signup the users. The APIs are working fine in backend. It seems to be an issue of frontend.
SignUp.js File:
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
export const SignUp = (props) => {
const host = "http://localhost:3000";
let navigate = useNavigate();
const [credentials, setCredentials] = useState({
name: "",
email: "",
password: "",
cpasswortd: "",
});
const handleSubmit = async (e) => {
e.preventDefault();
const { name, email, password } = credentials;
const response = await fetch(`${host}/api/auth/createuser`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name,
email,
password,
}),
});
const json = await response.json();
console.log(json);
if(json.success){
// Save the auth token and redirect
localStorage.setItem("token", json.authtoken);
navigate("/login");
props.showAlert("Account created successfully" , "success")
} else {
props.showAlert("Invalid Details" , "danger")
}
};
const onChange = (e) => {
setCredentials({ ...credentials, [e.target.name]: e.target.value });
};
return (
<>
<section className="vh-100" style={{ backgroundColor: "white" }}>
<div className="container h-100">
<div className="row d-flex justify-content-center align-items-center h-100">
<div className="col-lg-12 col-xl-11">
<div className="card text-black" style={{ borderRadius: "25px" }}>
<div className="card-body p-md-5">
<div className="row justify-content-center">
<div className="col-md-10 col-lg-6 col-xl-5 order-2 order-lg-1">
<p className="text-center h1 fw-bold mb-5 mx-1 mx-md-4 mt-4">
Sign up
</p>
<form onSubmit={handleSubmit} className="mx-1 mx-md-4">
<div className="d-flex flex-row align-items-center mb-4">
<div className="form-outline flex-fill mb-0">
<input
type="text"
id="name"
onChange={onChange}
name="name"
className="form-control"
required
/>
<label className="form-label" htmlFor="name">
Your Name
</label>
</div>
</div>
<div className="d-flex flex-row align-items-center mb-4">
<div className="form-outline flex-fill mb-0">
<input
type="email"
id="email"
name="email"
onChange={onChange}
className="form-control"
aria-describedby="emailHelp"
required
/>
<label className="form-label" htmlFor="email">
Your Email
</label>
</div>
</div>
<div className="d-flex flex-row align-items-center mb-4">
<div className="form-outline flex-fill mb-0">
<input
type="password"
onChange={onChange}
name="password"
minLength={5}
id="password"
required
className="form-control"
/>
<label className="form-label" htmlFor="password">
Password
</label>
</div>
</div>
<div className="d-flex flex-row align-items-center mb-4">
<div className="form-outline flex-fill mb-0">
<input
type="password"
onChange={onChange}
name="cpassword"
minLength={5}
id="cpassword"
required
className="form-control"
/>
<label className="form-label" htmlFor="cpassword">
Confirm your password
</label>
</div>
</div>
<div className="d-flex justify-content-center mx-4 mb-3 mb-lg-4">
<button
type="submit"
className="btn btn-primary btn-lg"
>
Register
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</>
);
};
Login.js File:
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
export const Login = (props) => {
const host = "http://localhost:3000";
const [credentials, setCredentials] = useState({ email: "", password: "" });
let navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
const response = await fetch(`${host}/api/auth/login`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
email: credentials.email,
password: credentials.password,
}),
});
const json = await response.json();
console.log(json);
if (json.success) {
// Save the auth token and redirect
localStorage.setItem("token", json.authtoken);
navigate("/");
props.showAlert("Logged In Successfully", "success");
} else {
props.showAlert("Invalid Credentials", "danger");
}
};
const onChange = (e) => {
setCredentials({ ...credentials, [e.target.name]: e.target.value });
};
return (
<section className="vh-100">
<div className="container-fluid">
<div className="row">
<div className="col-sm-6 text-black">
<div className="px-5 ms-xl-4">
<i
className="fas fa-crow fa-2x me-3 pt-5 mt-xl-4"
style={{ color: "#709085" }}
></i>
<span className="h1 fw-bold mb-0">iNotebook</span>
</div>
<div className="d-flex align-items-center h-custom-2 px-5 ms-xl-4 mt-5 pt-5 pt-xl-0 mt-xl-n5">
<form onSubmit={handleSubmit} style={{ width: "23rem" }}>
<h3
className="fw-normal mb-3 pb-3"
style={{ letterSpacing: "1px" }}
>
Log in
</h3>
<div className="form-outline mb-4">
<input
type="email"
id="email"
name="email"
onChange={onChange}
value={credentials.email}
className="form-control form-control-lg"
required
/>
<label className="form-label" htmlFor="email">
Email address
</label>
</div>
<div className="form-outline mb-4">
<input
type="password"
name="password"
onChange={onChange}
value={credentials.password}
id="password"
className="form-control form-control-lg"
required
/>
<label className="form-label" htmlFor="password">
Password
</label>
</div>
<div className="pt-1 mb-4">
<button
className="btn btn-info btn-lg btn-block"
type="submit"
>
Login
</button>
</div>
<p>
Don't have an account?
<a href="/signup" className="link-info">
Signup here
</a>
</p>
</form>
</div>
</div>
</div>
</div>
</section>
);
};
auth.js (backend file):
const express = require("express");
const router = express.Router();
const User = require("../models/User");
const { body, validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const fetchUser = require("../middleware/fetchUser");
const JWT_SECRET = "Harryisagoodboy";
// ROUTE 1: Create a User using: POST "/api/auth/createuser" . No login required.
router.post(
"/createuser",
[
body("name", "Enter a valid name.").isLength({ min: 3 }),
body("email", "Enter a valid email").isEmail(),
body("password", "Enter a password of minimum 5 characters.").isLength({
min: 5,
}),
],
async (req, res) => {
// If there are errors, return the Bad request and the errors
let success = false;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({success, errors: errors.array() });
}
try {
// Check whether the user with this email exist already
let user = await User.findOne({ email: req.body.email });
if (user) {
return res
.status(400)
.json("Sorry a user with this email already exists.");
}
const salt = await bcrypt.genSalt(10);
const secPass = await bcrypt.hash(req.body.password, salt);
user = await User.create({
name: req.body.name,
password: secPass,
email: req.body.email,
});
const data = {
user: {
id: user.id,
},
};
const authToken = jwt.sign(data, JWT_SECRET);
// .then(user => res.json(user))
// .catch(err => {console.log(err),
// res.json({error: "Please enter a unique email ID"})})
success=true;
res.json({ success, authToken });
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
}
);
// ROUTE 2: Authenticate a User using: POST "/api/auth/login" . No login required.
router.post(
"/login",
[
body("email", "Enter a valid email").isEmail(),
body("password", "Password cannot be blank").exists(),
],
async (req, res) => {
let success = false;
// If there are errors, return the Bad request and the errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({success , errors: errors.array() });
}
const {email , password} = req.body;
try {
// Checks if the email already exists
let user = await User.findOne({email})
if(!user){
res.status(400).json({success, error: "Please enter correct credentials"})
}
// Compares the password entered by the user with stored password in database.
const comparePassword = await bcrypt.compare(password , user.password);
// If password does not matches.
if(!comparePassword){
res.status(400).json({success, error: "Please enter correct credentials"})
}
const data = {
user: {
id: user.id,
},
};
// Getting an Authentication token on the basis of user's id as 'Payload' and 'JWT SECRET'
const authToken = jwt.sign(data, JWT_SECRET);
success=true;
res.json({ success, authToken });
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
}
);
// ROUTE 3: Get Logged-in User Details using: POST "/api/auth/getuser" . Login required.
router.post(
"/getuser",
fetchUser,
async (req, res) => {
try {
userID = req.user.id;
const user = await User.findById(userID).select("-password")
res.send(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Internal Server Error");
}
}
)
module.exports = router;
middleware fetchUser.js file:
const jwt = require("jsonwebtoken");
const JWT_SECRET = "Harryisagoodboy";
const fetchUser = (req, res, next) => {
// Get the user from the JWT token and add id to req object
const token = req.header("auth-token");
if (!token) {
res.status(401).send({ error: "Please authenticate using a valid token" });
}
try {
const data = jwt.verify(token, JWT_SECRET);
req.user = data.user;
next();
} catch (error) {
res.status(401).send({ error: "Please authenticate using a valid token" });
}
};
module.exports = fetchUser;