Identifier … has already been declared
Solution 1
In your code, you're overriding the email
variable, which was created with the const
keyword (aka: can't be reassigned).
Jeena's answer probably solves the problem, but it seems you have a deeper problem.
User.findOne({email}, (err, user){}
is async. So the code below this code will probably fail.
You PROBABLY have to rewrite your code as:
exports.signin = (req,res) => {
//find the user based on email
const { email, password } = req.body
User.findOne({email}, (err, user) => {
//if error or no user
if (err || !user) {
return res.status(401).json({
error: "User with that email does not exists. Please signin."
});
}
//if user is found make sure the email and password match
// create authenticate method in model and use here
if (!user.authenticate(password))
return res.status(401).json({
error: "Email and password do not match."
});
//generate a token with user id and secret
const token = jwt.sign({_id: user._id}, process.env.JWT_SECRET);
//persist the token as 't' in cookie with expiry date
res.cookie("t", token, {expire: new Date() + "9999"});
//return response with user and token to frontend client
const {_id, name, email} = user;
return res.json({token, user:{_id, email, name}});
})
}
The cookies
and response
must be inside the MongoDB query, so you DO have the user.
Solution 2
const {_id, name, email} = user;
is called destructuring and will assign new variables with the same names of their objects.
So this:
const {_id, name, email} = user;
Is the same as:
const _id = user._id;
const name = user.name;
const email = user.email;
That's said, you're problably redefining email
variable, which is set with the const
keyword. It means you cannot reassign it.
What you can do is:
const {_id, name, email: _email} = user;
return res.json({token, user:{_id, name, email: _email}});
This will make the email
field to be assigned to the _email
variable, avoiding conflict.
Admin
Updated on August 21, 2022Comments
-
Admin over 1 year
I'm building a social network to learn nodejs and reactjs. Currently while building the backend in the
/signin
debug with postman I can't even launch the node server, the cmd throws the following error:\node_react\2\nodeapi\controllers\auth.js:40 const {_id, name, email} = user; ^ SyntaxError: Identifier 'email' has already been declared
The code snippet which throws the error is the following:
//generate a token with user id and secret const token = jwt.sign({_id: user._id}, process.env.JWT_SECRET); //persist the token as 't' in cookie with expiry date res.cookie("t", token, {expire: new Date() + 9999}); //return response with user and token to frontend client const {_id, name, email} = user; return res.json({token, user:{_id, email, name}});
The complete auth.js code is the following :
const jwt = require("jsonwebtoken"); require ('dotenv').config(); const User = require("../models/user"); exports.signup = async (req, res) => { const userExists = await User.findOne({email: req.body.email}); if(userExists) return res.status(403).json({ error: "Email is taken!" }); const user = await new User(req.body); await user.save(); res.status(200).json({ message: "Signup success! Please login:)" }); }; exports.signin = (req,res) => { //find the user based on email const { email, password } = req.body User.findOne({email}, (err, user) => { //if error or no user if (err || !user) { return res.status(401).json({ error: "User with that email does not exists. Please signin." }); } //if user is found make sure the email and password match // create authenticate method in model and use here if (!user.authenticate(password)) return res.status(401).json({ error: "Email and password do not match." }); }) //generate a token with user id and secret const token = jwt.sign({_id: user._id}, process.env.JWT_SECRET); //persist the token as 't' in cookie with expiry date res.cookie("t", token, {expire: new Date() + "9999"}); //return response with user and token to frontend client const {_id, name, email} = user; return res.json({token, user:{_id, email, name}}); }