Identifier … has already been declared

12,205

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.

Share:
12,205
Admin
Author by

Admin

Updated on August 21, 2022

Comments

  • Admin
    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}});      
    }