Mitchell
Mitchell

Reputation: 11

My registration form wont redirect after subimtting - node.js

I am creating a registration form with node/express for my website. I have all of the routes setup and my database is connected.

I am having issues when the user is at the step to submit a registration form for the site.

Here is my code:

const express = require('express');
const app = express();
const router = express.Router();
const bodyParser = require("body-parser");
const User = require('../schema/userSchema');
const bcrypt = require("bcrypt");
app.set("view engine", "pug");
app.set("views","views");
app.use(bodyParser.urlencoded({extended:false}));

router.get("/", (req,res,next) => {
        res.status(200).render("register");
})

router.post("/", async (req,res,next) => {
        var firstName = req.body.firstName.trim();
        var lastName = req.body.lastName.trim();
        var username = req.body.username.trim();
        var email = req.body.email.trim();
        var password = req.body.password;

        var payload = req.body;

        if(firstName && lastName && username && email && password){
                var user = await User.findOne({
                    $or: [
                        { username: username},
                        { email: email}
                    ]
                })
                .catch((error) => {
                    console.log(error);
                    payload.errorMessage = "Error.";
                    res.status(200).render("register",payload);
                });

            if(user == null){
                var data = req.body;
                data.password = await bcrypt.hash(password, 10);
                User.create(data)
                .then((user) =>{
                    req.session.user = user;
                    return res.redirect("/");
                })

            }
            else{
                if(email == user.email){
                    payload.errorMessage = "email already in use.";
                }
                else{
                    payload.errorMessage = "username already in use.";
                }
                res.status(200).render("register", payload);
            }
        }
        
        else{
            payload.errorMessage = "Make sure each feild has a valid value.";
            res.status(200).render("register");
        }
        res.status(200).render("register");
})
module.exports = router;

When I go to the terminal window in VSCode, I get this error:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:387:5) at ServerResponse.setHeader (node:_http_outgoing:603:11) at ServerResponse.header (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\response.js:794:10) at ServerResponse.send (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\response.js:174:12) at done (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\response.js:1035:10) at Object.exports.renderFile (C:\Users\Mmart\Desktop\twitter\node_modules\pug\lib\index.js:448:12) at View.exports.__express [as engine] (C:\Users\Mmart\Desktop\twitter\node_modules\pug\lib\index.js:493:11) at View.render (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\view.js:135:8) at tryRender (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\application.js:657:10) at Function.render (C:\Users\Mmart\Desktop\twitter\node_modules\express\lib\application.js:609:3)

The goal is for the page to redirect to the home page after clicking submit, but once the button is clicked, the page just refreshes and clears out the form data. It does, however, save the form data to my mongoDB instance.

Also My HTML is built using the files home.pug, login.pug and register.pug

Upvotes: 0

Views: 59

Answers (1)

Omar Omeiri
Omar Omeiri

Reputation: 1833

This error happens when you try to send multiple responses for the same request. res.send,status,render... does not stop the execution of the next lines. Your should always use the return early technique when you want no further execution.

Maybe if you clean up your code a bit, it might work.

router.post('/', async (req, res, next) => {
  // You should use the optional chaining here "?."
  // If any of the fields is undefined, your code will break
  // when calling .trim()
  const firstName = req.body?.firstName?.trim();
  const lastName = req.body?.lastName?.trim();
  const username = req.body?.username?.trim();
  const email = req.body?.email?.trim();
  const {
    password,
  } = req.body;
  const payload = req.body;

  // You can check if any field is invalid and return
  // early instead of wrapping your entire block inside an if statement
  if (
    !firstName
    || !lastName
    || !username
    || !email
    || !password
  ) {
    payload.errorMessage = 'Make sure each field has a valid value.';
    res.status(400).render('register');
    return;
  }

  try {
    const user = await User.findOne({
      $or: [
        { username },
        { email },
      ],
    });

    if (!user) {
      const data = req.body;
      data.password = await bcrypt.hash(password, 10);
      const user = await User.create(data)
      req.session.user = user;
      res.redirect('/');
      return;
    }

    if (email === user.email) {
      payload.errorMessage = 'email already in use.';
    } else {
      payload.errorMessage = 'username already in use.';
    }
    res.status(400).render('register', payload);
  } catch (err) {
    console.log(error);
    payload.errorMessage = 'Error.';
    res.status(500).render('register', payload);
  }
});

Upvotes: 1

Related Questions