DEV Community

Cover image for Building A Simple React Login Form: A Step By Step Guide.
Pauline Oraro
Pauline Oraro

Posted on

Building A Simple React Login Form: A Step By Step Guide.

In today's digital age, user authentication is a fundamental aspect of web development. Whether you are building a social media platform, an e-commerce site or a personal blog you need a login form to secure user data. In this step-by-step guide we will walk you through the process of building a simple login form using react. By the end of this tutorial you will have a functional login form that you can integrate into your React application. You can view the code and live demo.

Table of contents

Prerequisites

Before we dive into the tutorial, make sure you have the following;

  • Node.js and npm- Ensure you have Node.js and npm(Node Package Manager) installed on your machine. You can download and install them from the official Node.js website.

  • Basic understanding of React- Familiarize yourself with the basics of React if you haven't already. You can check out the official react documentation for a quick start.

  • Code editor- You can use a code editor of your choice.

Setting up the project

Let's start by creating a new react application using create-react-app. Open your terminal and run the following command;

npx create-react-app react-login-form
Enter fullscreen mode Exit fullscreen mode

This command will create a new React project named "react-login-form". Once the project is created, navigate to the project directory;

cd react-login-form
Enter fullscreen mode Exit fullscreen mode

Now you can open the project in your favourite code editor. Here is what the folder structure should look like;

folder structure
We will work primarily within the src directory for this tutorial.

Creating the LoginForm component in App.js

This component defines a simple registration form with validation. The form allows users to input their username, email address, password and confirm password. Here is a step by step explanation of the code;

import React from 'react';
import './App.css';

function App() {
  class LoginForm extends React.Component{
    constructor(){
      super();
      this.state = {
        //holds the users values for the form fields
        input: {},
        //holds errors that occur during form submission
        errors: {}
      };
      this.handleChange = this.handleChange.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }
    //called when the user interacts with any input field
    handleChange(event){
      let input = this.state.input;
      //identify the input field based on its name attribute
      input[event.target.name] = event.target.value;
      this.setState({input})
    }
    //called when the form is submitted
    handleSubmit(event){
      //prevents the default form submission behavior
      event.preventDefault();
      //calls the validate function to check the validity of the form inputs and if it is valid the form is submitted
      if (this.validate()){
        console.log(this.state);

        let input = {};
        input["username"] = "";
        input["email"] = "";
        input["password"] = "";
        input["confirm_password"] = "";
        this.setState({input : input});

        alert("Form is submitted");
      }
    }

    validate() {
      let input = this.state.input;
      let errors = {};
      let isValid = true;

      //checks if the username is null or undefined
      if (!input["username"]){
        isValid = false;
        errors["username"] ="Please enter your username";
      }

      if (typeof input["username"] !== "undefined"){
        const re = /^\S*$/;
        if(input["username"].length < 6 || !re.test(input["username"])){
          isValid = false;
          errors["username"] = "Please enter valid username"
        }
      }

      if(!input["email"]){
        isValid = false;
        errors["email"] = "Please enter your email address"
      }

      if(typeof input["email"] !== "undefined"){
        var pattern = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
        if(!pattern.test(input["email"])){
          isValid = false;
          errors["email"] = "Please enter a valid email address"
        }
      }

      if(!input["password"]){
        isValid = false;
        errors["password"] = "Please enter your password"
      }


      if(typeof input["password"] !== "undefined"){
        var patternPassword = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{8,})");
        if(!patternPassword.test(input["password"])){
          isValid = false;
          errors["password"] = "The password should contain atleast one lowercase, one uppercase, one digit and one special character. The password should be atleast 8 characters long."
        }
      }

      if ( typeof input["password"] !== "undefined" && typeof input["confirm_password"] !== "undefined"){
        if (input["password"] !== input["confirm_password"]){
          isValid = false;
          errors["confirm_password"] = "Passwords don't match"
        }
      }

      this.setState({errors: errors});

      return isValid;
    }
    render(){
      return(
        <div className='container'>
          <h1 className='text-center mb-4'>REGISTRATION FORM</h1>
          <form onSubmit={this.handleSubmit}>
            <div className='form-group'>
              <label for="username" className='form-label fs-5 fw-bold'>USERNAME:</label>
              <input
              type="text"
              name="username"
              value={this.state.input.username}
              onChange={this.handleChange}
              className='form-control fs-5'
              placeholder='Enter username'
              id="username"
              />
              <div className='text-danger form-text fw-bold fs-5'>{this.state.errors.username}</div>
            </div>
            <div className='form-group'>
              <label for="email" className='form-label fs-5 fw-bold'>EMAIL ADDRESS:</label>
              <input
              type="text"
              name="email"
              value={this.state.input.email}
              onChange={this.handleChange}
              className='form-control fs-5'
              placeholder='Enter Email'
              id="email"
              />
              <div className='text-danger form-text fw-bold fs-5'>{this.state.errors.email}</div>

              <div className='form-group'>
                <label for="password" className='form-label fs-5 fw-bold'>PASSWORD:</label>
                <input 
                type="password"
                name="password"
                value={this.state.input.password}
                onChange={this.handleChange}
                className='form-control fs-5'
                placeholder='Enter password'
                id="password"
                />
                <div className='text-danger form-text fw-bold fs-5'>{this.state.errors.password}</div>
              </div>

              <div className='form-group'>
                <label for="confirm-password" className='form-label fs-5 fw-bold'>CONFIRM PASSWORD:</label>
                <input 
                type="password"
                name="confirm-password"
                id="confirm-password"
                value={this.state.input.confirm_password}
                onChange={this.handleChange}
                className='form-control fs-5'
                placeholder='Enter confirm password'
                />
                <div className='text-danger form-text mb-5 fw-bold fs-5'>{this.state.errors.confirm_password}</div>
              </div>


            </div>
            <input 
              type="submit"
              value="SUBMIT"
              className='btn btn-success d-flex justify-content-center mx-auto mb-3 px-3'
              />
          </form>
        </div>
      )
    }
  }
  return (
    <div className="App">
      <LoginForm/>
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

The App component

This is the main component of the application. It contains the entire registration form.

The LoginForm component

LoginForm is a nested class component within the App component. It represents the registration form itself.

Constructor

The super() statement executes the parent component constructor function and your LoginForm component has access to all the functions of the parent component(React.Component).
The component state is initialized with two properties;

  • input which holds the user input values.

  • errors which hold any validation errors that occur during form submission.

The handleChange and handleSubmit methods are bound to the component using bind it ensures that "this" inside these methods refers to the LoginForm component.

handleChange() method

It is called whenever the user interacts with any input fields in the form.
It;

  • Retrieves the current input state.

  • Updates the value of the corresponding input field based on the name attribute of the input element that triggered the event.

  • Sets the updated input state using this.setState.

handleSubmit() method

It is called when the form is submitted. It prevents the default form submission behavior using event.preventDefault(). It calls the validate method to check the validity of the form inputs. If form is valid based on the validate method it logs the current state, clears the input fields and displays an alert message indicating that the form was submitted.

validate() method

It is responsible for validating the form inputs. It initializes input, errors, isValid as variables.

It checks if the username is empty and adds an error message to errors if it is empty. It checks if the username follows a pattern(atleast 6 characters without spaces) and adds an error message if it doesn't follow the pattern.

It checks if the email is empty and adds an error message if it is empty. It validates the email address format using a regular expression and if it doesn't match it adds an error message.

It checks if the password is empty and adds an error message if it is empty. It validates the password against a regular expression(atleast one lowercase, one uppercase, one digit, one special character and atleast 8 characters long). If the given password doesn't match the regular expression, it adds an error message.

It checks if the confirm password matches the password.

It updates the errors state with any validation errors and returns isValid.

render() method

It returns the JSX for rendering the form.

Each input field is associated with a name, value and onChange event handler. The value of each input field is bound to the corresponding property in the input state and the handleChange() method is called when the user interacts with the field.

Error messages are displayed below each input field based on the errors state.

Conclusion

In conclusion, this code defines a React application that contains a registration form component (LoginForm) with input validation. The registration form includes fields for username, email, password, and confirm password, and it provides error messages for each field when validation fails. Key points to note are:

  • The LoginForm component manages its state to store user input values and validation errors.

  • Input values and errors are updated in the component's state as users interact with the form.

  • The validate method checks the validity of form inputs based on specific criteria (e.g., username length, email format, password complexity, and password confirmation).

  • When the form is submitted, it prevents the default behavior, performs input validation, and displays an alert if the form is submitted successfully.

  • Upon successful submission, the form fields are cleared, and a success message is displayed.

You can view the code and live demo.

Top comments (0)