Search code examples
node.jsreactjsauthenticationregistryreact-fullstack

Why cannot react catch an error from the node?


I build a register page using React as Frontend, and Node Js as backend. However, when I try to check the delicate username. Axios from the Frontend doesn't show any error. I have written the catch in many different ways. But I still cannot find where the problem is. Could anyone help me out? Thanks!

Frontend

const handleSubmit = async (event) => {
    event.preventDefault();
    
    if (handleValidation()) {
      await axios.post(registerRoute, {
        username,
        email,
        password,
      }).then((response) => {
        console.log(response);
      }).catch((error) => {
         if (error.response.status === 11000) {
          console.log(error.response.data);
         }
      })
      navigate("/");
    }
  };

Backend

module.exports.register = async (req, res, next) => {
   const { username, email, password } = req.body;

   if (!username || typeof username !== 'string') {
      return res.json({status: 'error', message: 'Invalid username'})
   }

    const usernameExit = await Users.findOne({username: username})
    if (usernameExit) {
       return res.status(11000).json({ message: "Username already exit" });
    }

   if (!password || typeof password !== 'string') {
      return res.json({status: 'error', message: 'Invalid password'})
   }

  try {
    const hashedPassword = await bcrypt.hash(password, 2); 
    const user = new Users({
      username,
      email,
      password: hashedPassword,
    });
    user.save();
    delete user.password;
    return res.json({ status: true, user });
  } catch (error) {
   if (error.code === 11000) {
      return res.status(11000).json({ message: "Username already exit" });
   }
  }
};


Solution

  • First things first. In your back end endpoint you need to add the word await in before saving the document since you're using async/await for this method.

    await user.save();
    

    Second, you won't be able to delete the user's password this way because this is a MongoDB document and not a JavaScript object. You can convert the document to be a JS object which was explained in this question below. After you convert it to a JS object then you do delete user.password, not before.

    convert mongodb object to javascript object

    Third, you should always follow the industry best practices and use one of the HTTPS codes based on the situation. This way you know that a MongoDB error code is coming from MongoDB and not your endpoint because you setup a different status code like 404 or 400 for any custom error handling that you are doing.

    Here's the reference for the HTTPS codes - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status

    If you want to catch the status in Axios, you need to set the status like @Yozi mentioned and follow the approach below

    return res.status(400).json({message: "Some message here", user});
    

    This way Axios will catch the 400 status and throw an error in the console. If you customize the status like

    res.json({status: 'error'});
    

    You need to handle that differently in your front end. You can do something like

    console.log(res.data.status === 'error');