Search code examples
javascriptnode.jsreactjsmongodbmongoose

How do I solve Cannot access 'email' before initialization?


I am still new to MERN stack development. I have a http://localhost:8000/api/signin endpoint where the email and password is submitted. The backend code first checks if a user is already saved in MongoDB then the password submitted in the endpoint will be compared with the one saved in the database(mongodb).

/controllers/auth.js

exports.signin = (req, res) => {
  const { email, password } = req.body;
  const signInUser = async () => {
    try {
      // Check if user exists
      let findUser = await User.findOne({ email }); // promise is the new way of doing this instead of callback as of express 4.18 and mongoose 7.0.3

      console.log('findUser', findUser);

      if (!findUser) {
        return res.status(400).json({
          error: 'User with that email does not exist. Please signup'
        })
      }

      // authenticate
      if (!findUser.authenticate(password)) {
        return res.status(400).json({
          error: 'Email and password do not match'
        })
      }

      // generate a token and send to client
      const token = jwt.sign({_id: findUser._id}, process.env.JWT_SECRET, { expiresIn: '7d' });
      const {_id, name, email, role} = existingUser;

     return res.json({
      message: 'Yey!'
     })
    } catch (error) {
      console.log(error); // Sometimes this error is not displayed on postman

      return res.status(400).json({
        error: 'Something went wrong'
      })
    }
  }

  signInUser();
};

Problem: I am currently seeing a ReferenceError: Cannot access 'email' before initialization error. I think the error starts on line const {_id, name, email, role} = existingUser;

Do you have any idea how can I update my code to overcome the error?

Any help is greatly appreciated. Thank you.


Solution

  • existingUser is not defined and you are trying to destructure it. Instead you have to destructure the findUser which you have obtained above

    const {_id, name, role} = findUser;
    

    also don't destructure the email since you already have it above where you used it to find from the database. If you do it this might break the line let findUser = await User.findOne({ email }); since you are trying to access the email before initialization inside the function (initialization is the destructuring in this case const {_id, name, email, role} = findUser.

    if you really need to destructure the email you can do something like

    {_id, name, email: emailFromDb, role} = findUser.
    

    and now you can use the emailFromDb from there onwards