Building A Simple React Login Form: A Step By Step Guide.
Tags: webdev, react, tutorial, programmers
Published: 2023-09-23 07:57:55

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](https://github.com/Pauline-Oraro/react-login-form) and live [demo](https://react-login-form-one.vercel.app/).

#### Table of contents

- [Prerequisites](#prerequisites).

- [Setting up the project](#setting).

- [Creating the LoginForm component in App.js](#component).
               1. [The App component](#app).
               2. [The LoginForm component](#login).
               3. [Constructor](#constructor).
               4. [handleChange() method](#handlechange).
               5. [handleSubmit() method](#handlesubmit).
               6. [validate() method](#validate).
               7. [render() method](#render).

- [Conclusion](#conclusion).


## Prerequisites <a name="prerequisites"></a>
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](https://nodejs.org/en).

- **Basic understanding of React-** Familiarize yourself with the basics of React if you haven't already. You can check out the official [react documentation](https://react.dev/learn) for a quick start.

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

## Setting up the project <a name="setting"></a>
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
```
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
```
Now you can open the project in your favourite code editor. Here is what the folder structure should look like;

![folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eaihqmxzcxs6uof2r4ke.PNG)
We will work primarily within the **src** directory for this tutorial.

## Creating the LoginForm component in App.js <a name="component"></a>
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;

```

### The App component <a name="app"> </a>
This is the main component of the application. It contains the entire registration form.

### The LoginForm component <a name="login"></a>
**LoginForm** is a nested class component within the **App** component. It represents the registration form itself.

### Constructor <a name="constructor"></a>
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 <a name="handlechange"></a>
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 <a name="handlesubmit"></a>
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 <a name="validate"></a>
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 <a name="render"></a>
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 <a name="conclusion"></a>
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](https://github.com/Pauline-Oraro/react-login-form) and live [demo](https://react-login-form-one.vercel.app/).