Let’s Create a Modern Login Form on React | 02

Video Tutorial

Overview

After implementing the basics of our login/register forms everything from the layout, styling, and structure now we need to add some functionality to the form to make alive an can actually take actions (responsive), therefore we are going to create a validation system, that will let you tell if any input data is empty or not compatible with the data that you require, and that’s by telling the user where is the problem in such a nice way.

Also, we will try to make a password strength generator that will let us if the password that is going to be registered with is weak, medium or strong enough.

We are going to work on the Register Component only since the login and register boxes are pretty much the same.

Validating Form Inputs

The way that we are going to do that is by creating an errors array under the component’s state that will hold the validation errors that comes from the inputs (username, email, and password).

First, let’s create the methods that will allow us to manipulate the errors array (either add or remove an element from the array and update state)

...
//Add New Error Object to the array {elm: msg}
showValidationErr(elm, msg) {
  this.setState((prevState) => ({
    errors: [
      ...prevState.errors, {
        elm,
        msg
      }
    ]
  }));
}
//Remove a specific element from the array 
clearValidationErr(elm) {
  this.setState((prevState) => {
    let newArr = [];
    //Add all elements from the prev array to the new one that has a different element
    for (let err of prevState.errors) {
      if (elm != err.elm) {
        newArr.push(err);
      }
    }
    return {errors: newArr};
  });
}

Now we need to save the input data into our state (username, email, and password), we do that using the onChange event which means whenever there is a new character being typed on the input do something and in this case, we want to update the state.

...
//Update Username, password, and email on change event 
onUsernameChange(e) {
  this.setState({username: e.target.value});
  //We want to clear the error when ever the user type something new 
  this.clearValidationErr("username");
}

onEmailChange(e) {
  this.setState({email: e.target.value});
  this.clearValidationErr("email");
}

onPasswordChange(e) {
  this.setState({password: e.target.value});
  this.clearValidationErr("password");
}

also, make sure to bind it to the corresponding input elements for the event callback to work properly

<input
  type="text"
  name="username"
  className="login-input"
  placeholder="Username"
  onChange={this
  .onUsernameChange
  .bind(this)}/>
//Do it for all the other inputs

To render the errors to the user we need to check first which elements are having a validation error then render them below each input that has the error.

Under the render method check for where the error is.

render() {
...
    //NULL by default (help us check when rendering)
    let usernameErr = null,
      passwordErr = null,
      emailErr = null;
    //Loop and find which ones has the error
    for (let err of this.state.errors) {
      //Assign the validation error message 
      if (err.elm == "username") {
        usernameErr = err.msg;
      }
      if (err.elm == "password") {
        passwordErr = err.msg;
      }
      if (err.elm == "email") {
        emailErr = err.msg;
      }
      //No (else if or else) statements cause we need to check for all possible elements
    }
}

So we can later use it like this to weather render or not

//Make sure to put this bellow each corresponding input (change it with the right variable)
render() {
...
    <small className="danger-error">{usernameErr
        ? usernameErr
        : ""}
    </small>
}

The last thing is to show this validation errors whenever there is a needs to, so when we submit the registration form we have to check for which inputs are empty and show the error for the corresponding elements.

submitRegister(e) {
  //Check for all input fields and show errors if empty (you can implement other cases!)
  if (this.state.username == "") {
    this.showValidationErr("username", "Username Cannot be empty!");
  }
  if (this.state.email == "") {
    this.showValidationErr("email", "Email Cannot be empty!");
  }
  if (this.state.password == "") {
    this.showValidationErr("password", "Password Cannot be empty!");
  }
}

You can go ahead and try to submit an empty registration form you should get rejected and you would get validation errors, Nice!

Password Strength

So for the password length generator, we need to check for the entered password length and render regarding to its length.

Therefore we need a state variable that holds the current state of the password (weak, medium or strong) and that is going to be determined while typing the password (on password change).

First, check for password length and update the state regarding that.

onPasswordChange(e) {
...
  //By default the state is weak
  this.setState({pwdState: "weak"});
  if (e.target.value.length > 8) {
    this.setState({pwdState: "medium"});
  } else if (e.target.value.length > 12) {
    this.setState({pwdState: "strong"});
  }
}

For that, we need to determine the current state of the password whenever we need to update (render) the component.

render() {
...
  //states are by default false = (do not render)
  let pwdWeak = false,
    pwdMedium = false,
    pwdStrong = false;
  //Weak password set onlt the pwdWeak to true, cause render only the first bar 
  if (this.state.pwdState == "weak") {
    pwdWeak = true;
  } else if (this.state.pwdState == "medium") {
    //Medium pwd then render the weak and medium bars 
    pwdWeak = true;
    pwdMedium = true;
  } else if (this.state.pwdState == "strong") {
    //Strong, render all the previoud bars 
    pwdWeak = true;
    pwdMedium = true;
    pwdStrong = true;
  }
}

So we check for the current state and we tell which bar (color) needs to be rendered in the right order (weak > medium > strong) each one renders the previous ones as well so we can simulate a passwrod length generator.

We need to render the password length bars below the password input filed.

/*Render a container that holds the state bars, by adding the show class to the classNames list we can either render the current bar or no and that is depending on the password state */
render() {
...
 {this.state.password && <div className="password-state">
    <div
      className={"pwd pwd-weak " + (pwdWeak
      ? "show"
      : "")}></div>
    <div
      className={"pwd pwd-medium " + (pwdMedium
      ? "show"
      : "")}></div>
    <div
      className={"pwd pwd-strong " + (pwdStrong
      ? "show"
      : "")}></div>
  </div>}
}

You can grab the stylesheet we are using from Github

Now you can try the password strength generator by typing different passwords also, you can use other methods for guessing the strength of a password.

What’s Next

Hopefully, you have enjoyed coding the Login/Register Form Boxes on React, you can now take this form and implement more features so you can include it in your application.

No Comments Yet