0

Hey I'm looking for redirect a React page to Express page. The purpose is to send a mail if the user forgot his password. I tried to use Router but that send me on 'localhost:3000/forgot_password' and not 'localhost:3001/forgot_password'.

However that works with my submit form in my signup part. Why ?

My code is a bit messy so I'll comment the important part.

Here is the express part :

const bodyParser = require('body-parser')
const express = require('express')
const mysql = require('mysql')
const randomString = require('randomstring')
const bcrypt = require('bcrypt')

const app = express()
const router = express.Router()

app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: false}))
app.use((req, res, next) => {
    req.db = mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '00000000',
        database: 'Matcha'
    });
    next();
});

router.get('/users', (req, res) => {
    req.db.query("SELECT * FROM Users;", (err, rows, fields) => {
        if(err)
        return(res.send(err) && console.log(err));
      
        res.json(rows);
    });
});



router.post('/check_signUp', (req, res) => {
    console.log(req.body);

    const saltRounds = 10;
    const password = req.body.password;

    bcrypt.hash(password, saltRounds, function(err, hashPassword) {
        const randomKey = randomString.generate(15)
        console.log(req.body.username, password, req.body.mail, randomKey)
        req.db.query(`INSERT INTO Users (username, password, mail, randomKey) VALUES ('${req.body.username}', '${hashPassword}', '${req.body.mail}', '${randomKey}');`, (err, rows, fields) => {
            if(err)
                return(res.send(err) && console.log(err));
            bcrypt.compare('ffffff', '$2b$10$6707gWLRGjqGwKJzXx6Dt.CH00c0rRlioy8KdcWc4ze18LoL2YHeC', function(err, res) {
                console.log(res)
            });
            res.redirect('/');
        })
    })
})

// HERE IS THE IMPORTANT PART. I need to go in this router.get

router.get('/change_password', (req, res) => {
    res.send('OK');
});

// END OF THE IMPORTANT PART

app.use(router)
app.set('port', (process.env.PORT || 3001))
app.listen(app.get('port'), () => {
  console.log(`Listening on ${app.get('port')}`)
})

And here the react part :

import React, { Component } from 'react';
import './SignIn.css';
import { BrowserRouter as Router, Link } from 'react-router-dom';


class SignIn extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        valueUsername: '',
        valuePassword: '',
        users: [],
        validLog: '_',
        validMessage: '_'
      };

      this.changeUsername = this.changeUsername.bind(this);
      this.changePassword = this.changePassword.bind(this);
      this.submitForm = this.submitForm.bind(this);
      this.checkMatch = this.checkMatch.bind(this);
    }

    async componentDidMount() {
      const response = await fetch('/users')
      const users = await response.json()
      this.setState({users: users})
    }
  
    changeUsername(event) {
      this.setState({valueUsername: event.target.value}); 
    }

    changePassword(event) {
      this.setState({valuePassword: event.target.value});
    }

    checkMatch(valueUsername, valuePassword) {
      let users = this.state.users;
      let valueMatch = 0;

      users.forEach((user) => {
        console.log(user['username']);
        if (user['username'].toUpperCase() === valueUsername.toUpperCase()) {
          valueMatch = 1;
          console.log(user.password);
          if (user.password === valuePassword)
            valueMatch = 2;
          return;
        }
      });
      return valueMatch;
    }

    submitForm(event) {
      let match = this.checkMatch(this.state.valueUsername, this.state.valuePassword);
      console.log(match);
      if (match != 2) {
        event.preventDefault();
        this.setState({valuePassword: ''});

        if (match == 1) {
          this.setState({validLog: 'Wrong password'});
          this.setState({validMessage: 'Forgot it ? Click here'})
        }
        else
          this.setState({validLog: 'Username doesn\'t exist'});
      }
    }
  
    render() {
      let validLogColor;
      let validMessageColor;
      let validMessage = this.state.validMessage;

      if (this.state.validLog === '_')
        validLogColor = 'SignIn_validNone';
      else
        validLogColor = 'SignIn_validRed';


      if (this.state.validMessage === '_')
        validMessageColor = 'SignIn_validNone'
      else if (this.state.validMessage === 'Forgot it ? Click here') {
        validMessageColor = 'SignIn_validBlack'

//NEXT TO THE IMPORTANT PART -> I insert a link who normally have to go in my router.get but go on 'localhost:3000/forgot_password' instead of 'localhost:3001/forgot_password'

        validMessage = <Link to="/change_password">{this.state.validMessage}</Link>

//END OF THE NEXT IMPORTANT PART
      }
      else
        validMessageColor = 'SignIn_validBlue'
        

      return (
        <Router>
          <div id='SignIn'>
            <form action='test.html' method='POST' id='SignIn_form' onSubmit={this.submitForm}>
                <div id='SignIn_emptyInput'></div>
                <input type="text" placeholder="Username" name='username' value={this.state.valueUsername} onChange={this.changeUsername} />
                <input type="password" placeholder="Password" name='password' value={this.state.valuePassword} onChange={this.changePassword} />
                <input id='submit' type="submit" value="SIGN IN" />
            </form>
            <div id='SignIn_validAndSentence'><span id='SignUp_signSentence' onClick={this.props.changeForSignUp}>Not member yet ? <span id='SignIn_signWord'>SIGN UP</span></span>
              <div id='SignIn_validLog' className={validLogColor}>{this.state.validLog}</div>

              //THIS IS THE IMPORTANT PART

              <div id='SignIn_validMessage' className={validMessageColor}>{validMessage}</div>

              // END OF THE IMPORTANT PART

            </div>
          </div>
        </Router>
      );
    }
  }
  export default SignIn;

And that works with my signup part :

import React, { Component } from 'react';
import './SignUp.css';


class SignUp extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        valueMail: '',
        valuePassword: '',
        valueUsername: '',
        validMail: 'false',
        validPassword: 'unsafe',
        validUsername: 'true',
        users: []
      };
  
      this.changeMail = this.changeMail.bind(this);
      this.changePassword = this.changePassword.bind(this);
      this.changeUsername = this.changeUsername.bind(this);
      this.submitForm = this.submitForm.bind(this);
      this.checkValid = this.checkValid.bind(this);
    }

    async componentDidMount() {
      const response = await fetch('/users')
      const users = await response.json()
      this.setState({users: users})
    }
  
    changeMail(event) {
      this.setState({valueMail: event.target.value});
      this.checkValid('mail', event.target.value);
    }

    changePassword(event) {
      this.setState({valuePassword: event.target.value});
      this.checkValid('password', event.target.value);
    }

    changeUsername(event) {
      this.setState({valueUsername: event.target.value}); 
      this.checkValid('username', event.target.value);
    }
  
    submitForm(event) {      
      if (!this.state.valueMail || this.state.validMail === false || this.state.validMail === 'taken'
      || !this.state.valuePassword || this.state.validPassword === 'tooLong' || this.state.validPassword === 'unsafe'
      || !this.state.valueUsername || this.state.validUsername === false || this.state.validUsername === 'taken')
        event.preventDefault();
        if (!this.state.valueMail || this.state.validMail === false || this.state.validMail === 'taken')
          this.setState({valueMail: ''})
        if (!this.state.valuePassword || this.state.validPassword === 'tooLong' || this.state.validPassword === 'unsafe')
          this.setState({valuePassword: ''});
        if (!this.state.valueUsername || this.state.validUsername === false || this.state.validUsername === 'taken')
          this.setState({valueUsername: ''});
      
    }

    checkValid(elem, value) {

      if (elem == 'mail' && value) {
        let checkMail = new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
        if (value.length > 30)
          this.setState({validMail: 'tooLong'});
        else if (checkMail.test(value))
          this.setState({validMail: true});
        else
          this.setState({validMail: false});
      }
      else if (elem == 'password' && value) {
        let checkPasswordWeak = new RegExp(/.{4,}/);
        let checkPasswordSecure = new RegExp(/^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,}$|^.{12,}$/);
        if (value.length > 30)
          this.setState({validPassword: 'tooLong'});
        else if (checkPasswordSecure.test(value))
          this.setState({validPassword: 'secure'});
        else if (checkPasswordWeak.test(value))
          this.setState({validPassword: 'weak'});
        else
          this.setState({validPassword: 'unsafe'});
      }
      else if (elem == 'username' && value) {
        let checkUsernameCaracters = new RegExp(/^[^\s!@#$&*.><?`~%^()+=§"'|\\\/]+$/);
        if (value.length > 30)
          this.setState({validUsername: 'tooLong'});
        else if (!checkUsernameCaracters.test(value))
          this.setState({validUsername: false});
        else
          this.setState({validUsername: true});
      }


      if (elem == 'mail' || elem == 'username') {
        let users = this.state.users;
        users.forEach((user) => {
          if (user[elem].toUpperCase() === value.toUpperCase()) {
            if (elem == 'mail')
              this.setState({validMail: 'taken'});
            else if (elem == 'username')
              this.setState({validUsername: 'taken'});
            return;
          }
        });
      }
    }
  
    render() {

      let validMail;
      let validMailColor;
      let checked = '\u2713';
      let wrong = '\u2717';

      if (this.state.valueMail && this.state.validMail === true) {
        validMail = 'Valid mail ' + checked;
        validMailColor = 'SignUp_validGreen';
      }
      else if (this.state.valueMail && this.state.validMail === 'taken') {
        validMail = 'Mail already used ' + wrong;
        validMailColor = 'SignUp_validRed';
      }
      else if (this.state.valueMail && (this.state.validMail === 'tooLong' || this.state.validMail === false)) {
        validMail = 'Mail incorect ' + wrong;
        validMailColor = 'SignUp_validRed';
      }
      else {
        validMail = '_';
        validMailColor = 'SignUp_validNone';
      }

      
      let validPassword;
      let validPasswordColor;

      if (this.state.valuePassword && this.state.validPassword === 'tooLong') {
        validPassword = 'Password too long ' + wrong;
        validPasswordColor = 'SignUp_validRed';
      }
      else if (this.state.valuePassword && this.state.validPassword === 'unsafe') {
        validPassword = 'Unsafe password ' + wrong;
        validPasswordColor = 'SignUp_validRed';
      }
      else if (this.state.valuePassword && this.state.validPassword === 'weak') {
        validPassword = 'Password weak ~';
        validPasswordColor = 'SignUp_validOrange';
      }
      else if (this.state.valuePassword && this.state.validPassword === 'secure') {
        validPassword = 'Secure password ' + checked;
        validPasswordColor = 'SignUp_validGreen';
      }
      else {
        validPassword = '_';
        validPasswordColor = 'SignUp_validNone';
      }


      let validUsername;
      let validUsernameColor;

      if (this.state.valueUsername && this.state.validUsername === true) {
        validUsername = 'Valid Username ' + checked;
        validUsernameColor = 'SignUp_validGreen';
      }
      else if (this.state.valueUsername && this.state.validUsername === 'taken') {
        validUsername = 'Username already used ' + wrong;
        validUsernameColor = 'SignUp_validRed';
      }
      else if (this.state.valueUsername && this.state.validUsername === 'tooLong' || this.state.valueUsername && this.state.validUsername === false) {
        validUsername = 'Username incorect ' + wrong;
        validUsernameColor = 'SignUp_validRed';
      }
      else {
        validUsername = '_';
        validUsernameColor = 'SignUp_validNone';
      }
        
      

      return (
        <div id='SignUp'>
        
        //HERE IS THE FORM THAT REDIRECT ME WELL IN 'localhost:3001/check_signUp'
        
          <form action='/check_signUp' method='POST' id='SignUp_form' onSubmit={this.submitForm}>
              <input type="text" placeholder="Mail" name='mail' value={this.state.valueMail} onChange={this.changeMail} />
              <input type="password" placeholder="Password" name='password' value={this.state.valuePassword} onChange={this.changePassword} />
              <input type="text" placeholder="Username" name='username' value={this.state.valueUsername} onChange={this.changeUsername} />
              <input id='submit' type="submit" value="SIGN UP" />
          </form>
          
          //END OF THE FORM
          
          <div id='SignUp_validAndSentence'><span id='SignUp_signSentence' onClick={this.props.changeForSignIn}> Already member ? <span id='SignUp_signWord'>SIGN IN</span></span>
            <div id='SignUp_validMail' className={validMailColor}>{validMail}</div>
            <div id='SignUp_validPassword' className={validPasswordColor}>{validPassword}</div>
            <div id='SignUp_validUsername' className={validUsernameColor}>{validUsername}</div>
          </div>
        </div>
      );
    }
  }
  export default SignUp;

So someone can explain me why that works with form but not with link ? Thx a lot

Jackal
  • 1,041
  • 1
  • 10
  • 13

2 Answers2

0

The Link component from react-router-dom is only intended to be used to navigate different routes as defined by react-router. In this case you probably just want to use a regular HTML anchor tag

<a href="localhost:3001/change_password">{this.state.validMessage}</a>

Faizan Virani
  • 134
  • 1
  • 11
  • That doesn't work. It render me on localhost:3000/change_password and not localhost:3001/change_password – Jackal Jun 28 '18 at 10:32
  • Sorry that was my mistake you need to put the full localhost:3001/change_password because you are effectively navigating to an external host, functionally equivalent to navigating to another website entirely. In order for it to work how you want, your express app should be serving your react content on the same port. https://stackoverflow.com/questions/35928766/whats-the-correct-way-to-serve-production-react-bundle-js-built-by-webpack – Faizan Virani Jun 28 '18 at 22:31
0

That works if I put :

<a href="localhost:3001/change_password">{this.state.validMessage}</a>

But I don't understand why I have to write all the path because I haven't to do that when I submit the form. Someone can explain me why ?

Jackal
  • 1,041
  • 1
  • 10
  • 13