React JS + Spring Boot Login and Registration Example

This tutorial will teach us how to develop Login and Registration features using Java, Spring Boot, JavaScript, React JS, and MySQL database.

Prerequisites

Before continuing this tutorial, make sure to develop and expose Login and Registration REST APIs using the below tutorial:
  • We create a React application.
  • We design a User Registration form.
  • We connect the React app with the Register REST API to save registered data in the MySQL database.
  • We design a Login form.
  • We connect the React App with Login REST API for database authentication.

Set Up Your React Project

First, you need to create a new React project. If you haven't already installed Node.js and npm, you'll need to do so from the Node.js official website. Use the following command to create a react application using the create-react-app tool:
npx create-react-app react-login-registration

Open React application is created. Next, let's understand important folders and files.

The package.json file contains all the required dependencies for our React JS project. Most importantly, you can check the current version of React that you are using. It has all the scripts to start, build, and eject our React app.

The public folder contains index.html. Since React is used to build a single-page application, we have this single HTML file to render all our components. It's an HTML template. It has a div element with id as root, and all our components are rendered in this div with index.html as a single page for the complete React app.

The src folder contains all the global Javascript and CSS files and all the custom components we will build.

index.js - This is the top renderer of your React app.

node_modules - All the packages installed by NPM or Yarn will reside inside the node_modules folder.

App.js - The App.js file contains the definition of our App component, which actually gets rendered in the browser, and this is the root component.

Adding Bootstrap in React Using NPM

Open a new terminal window, navigate to your project's folder, and run the following command:
$ npm install bootstrap --save

--save option add an entry in the package.json file

Open the src/index.js file and add the following code:

import 'bootstrap/dist/css/bootstrap.min.css';

Complete code index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

Create RegisterComponent

import React from 'react'

const RegisterComponent = () => {
  return (
    <div>RegisterComponent</div>
  )
}

export default RegisterComponent

Create HeaderComponent and FooterComponent

Let's create a new file named HeaderComponent.js, and within this file, create a component named HeaderComponent with the following code:

import React from 'react'
import { NavLink } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'

const HeaderComponent = () => {

  return (
    <div>
        <header>
            <nav className='navbar navbar-expand-md navbar-dark bg-dark'>
                <div>
                    <a href='http://localhost:3000' className='navbar-brand'>
                        Todo Management Application
                    </a>
                </div>
                <div className='collapse navbar-collapse'>
                    <ul className='navbar-nav'>
                            <li className='nav-item'>
                            <NavLink to="/todos" className="nav-link">Todos</NavLink>
                        </li>
                    </ul>

                </div>
                <ul className='navbar-nav'>
                        <li className='nav-item'>
                        <NavLink to="/register" className="nav-link">Register</NavLink>
                    </li>
                        <li className='nav-item'>
                        <NavLink to="/login" className="nav-link">Login</NavLink>
                    </li>

                    </ul>
            </nav>
        </header>

    </div>
  )
}

export default HeaderComponent

Make sure to import NavLink at the top from react-router-dom.

NavLink is a special kind of Link that knows whether or not it is "active" or "pending". This is useful when building a navigation menu, such as a breadcrumb or a set of tabs where you'd like to show which of them is currently selected.

Let's create a new file named FooterComponent.js, and within this file, create a component named FooterComponent with the following code:

import React from 'react'

const FooterComponent = () => {
    return (
        <div>
            <footer className = "footer">
                 <span className="text-muted">All Rights Reserved 2021 @JavaGuides</span>
            </footer>
        </div>
    )
}

export default FooterComponent

Add the CSS code below to the App.css File:

.footer {
  position: absolute;
  bottom: 0;
  width:100%;
  height: 50px;
  background-color: black;
  text-align: center;
  color: white;
}

Update App.js to use RegisterComponent

import './App.css';
import FooterComponent from './components/FooterComponent';
import  HeaderComponent  from './components/HeaderComponent';
import RegisterComponent from './components/RegisterComponent';

function App() {
  return (
    <div>
      <HeaderComponent />
      <RegisterComponent />
      <FooterComponent />
   </div>
  );
}

export default App;

Configure Routing in React App

To use React Router, you first have to install it using NPM:

npm install react-router-dom --save
Check the entry in the package.json file for React Router. 

Next, let's configure Routing in the App Component:
import './App.css';
import {BrowserRouter, Routes, Route } from 'react-router-dom';
import FooterComponent from './components/FooterComponent';
import HeaderComponent from './components/HeaderComponent';
import RegisterComponent from './components/RegisterComponent';

function App() {
  return (
    <div>
      <BrowserRouter>
        <HeaderComponent />
        <div className= "container">
          <Routes>
              <Route path = "/" element = { <RegisterComponent /> }></Route>
              <Route path = "/register" element = { <RegisterComponent /> }></Route>
            </Routes>
        </div>
        <FooterComponent />
        </BrowserRouter>
    </div>
  );
}

export default App;

Design User Registration Form

Let's open the RegisterComponent.js file and add the following content to it:

import React, { useState } from 'react'

const RegisterComponent = () => {

    const [name, setName] = useState('')
    const [username, setUsername] = useState('')
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')


    function handleRegistrationForm(e){

        e.preventDefault();

        const register = {name, username, email, password}

        console.log(register);
    }

  return (
    <div className='container'>
        <br /> <br />
        <div className='row'>
            <div className='col-md-6 offset-md-3'>
                <div className='card'>
                    <div className='card-header'>
                        <h2 className='text-center'> User Registration Form </h2>
                    </div>

                    <div className='card-body'>
                        <form>
                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Name </label>
                                <div className='col-md-9'>
                                    <input
                                        type='text'
                                        name='name'
                                        className='form-control'
                                        placeholder='Enter name'
                                        value={name}
                                        onChange={ (e) => setName(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Username </label>
                                <div className='col-md-9'>
                                    <input
                                        type='text'
                                        name='username'
                                        className='form-control'
                                        placeholder='Enter username'
                                        value={username}
                                        onChange={ (e) => setUsername(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>


                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Email </label>
                                <div className='col-md-9'>
                                    <input
                                        type='text'
                                        name='email'
                                        className='form-control'
                                        placeholder='Enter email address'
                                        value={email}
                                        onChange={ (e) => setEmail(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Password </label>
                                <div className='col-md-9'>
                                    <input
                                        type='password'
                                        name='password'
                                        className='form-control'
                                        placeholder='Enter password'
                                        value={password}
                                        onChange={ (e) => setPassword(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='form-group mb-3'>
                                <button className='btn btn-primary' onClick={ (e) => handleRegistrationForm(e)}>Submit</button>

                            </div>
                        </form>

                    </div>

                </div>
            </div>
        </div>


    </div>
  )
}

export default RegisterComponent

This RegisterComponent is designed to handle user registration. It uses the useState hook to manage the state for user input fields: name, username, email, and password

When the form is submitted via the handleRegistrationForm function, it prevents the default form submission behaviour, aggregates the user inputs into a single object, and logs this object.

Connect React App to Register REST API

We will use the Axios HTTP library to make REST API calls in our React application. Let's install Axios using the NPM command below:
npm add axios --save

Let's create an AuthService.js file, and within this file, write the below code to call Register REST API using Axios

import axios from "axios";

const AUTH_REST_API_BASE_URL = "http://localhost:8080/api/auth"

export const registerAPICall = (registerObj) => axios.post(AUTH_REST_API_BASE_URL + '/register', registerObj);

Next, change RegisterComponent.handleRegisterForm() method to call AuthService method:

    function handleRegistrationForm(e){

        e.preventDefault();

        const register = {name, username, email, password}

        console.log(register);

        registerAPICall(register).then((response) => {
            console.log(response.data);
        }).catch(error => {
            console.error(error);
        })
    }

The handleRegistrationForm attempts to register the user by calling registerAPICall with the user data. This API call returns a promise; it logs the response data on success and any errors if the promise is rejected. The component visually represents a user registration form structured using Bootstrap classes. It captures and handles user inputs through controlled components, updating the state with each keystroke.

Create LoginComponent

Let's create a LoginComponent and design the login form.

import React, { useState } from 'react'

const LoginComponent = () => {

    const [username, setUsername] = useState('')
    const [password, setPassword] = useState('')

    function handleLoginForm(e){

        e.preventDefault();

        console.log(username);
        console.log(password);

    }

  return (
    <div className='container'>
        <br /> <br />
        <div className='row'>
            <div className='col-md-6 offset-md-3'>
                <div className='card'>
                    <div className='card-header'>
                        <h2 className='text-center'> Login Form </h2>
                    </div>

                    <div className='card-body'>
                        <form>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Username or Email</label>
                                <div className='col-md-9'>
                                    <input
                                        type='text'
                                        name='username'
                                        className='form-control'
                                        placeholder='Enter username'
                                        value={username}
                                        onChange={ (e) => setUsername(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Password </label>
                                <div className='col-md-9'>
                                    <input
                                        type='password'
                                        name='password'
                                        className='form-control'
                                        placeholder='Enter password'
                                        value={password}
                                        onChange={ (e) => setPassword(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='form-group mb-3'>
                                <button className='btn btn-primary' onClick={ (e) => handleLoginForm(e)}>Submit</button>

                            </div>
                        </form>

                    </div>

                </div>
            </div>
        </div>


    </div>
  )
}

export default LoginComponent

This LoginComponent is structured to manage the login process. It utilizes the useState hook from React to manage state variables such as username and password. These variables hold the values entered into the form inputs, allowing the component to manage the form as a controlled component.

The handleLoginForm function is triggered when the form's submit button is clicked. This function prevents the default form submission action from managing submission asynchronously or logistically within React. It currently logs the username and password to the console, indicating a placeholder for where you would typically handle authentication, such as making an API call to validate credentials.

Configure Route for LoginComponent

Let's open the App.js file and add the following Route to the existing route:

<Route path='/login' element = { <LoginComponent /> }></Route>

Connect React App to Login REST API

In AuthService, write a code to call Login REST API using Axios:

export const loginAPICall = (usernameOrEmail, password) => axios.post(AUTH_REST_API_BASE_URL + '/login', { usernameOrEmail, password});

Next, change the handleLoginForm() method in LoginComponent to call the above method from the AuthService file:

    function handleLoginForm(e){

        e.preventDefault();

        loginAPICall(username, password).then((response) => {
            console.log(response.data);
        }).catch(error => {
            console.error(error);
        })

    }

Here is the complete LoginComponent code:

import React, { useState } from 'react'
import { loginAPICall } from '../services/AuthService';

const LoginComponent = () => {

    const [username, setUsername] = useState('')
    const [password, setPassword] = useState('')


    function handleLoginForm(e){

        e.preventDefault();

        loginAPICall(username, password).then((response) => {
            console.log(response.data);
        }).catch(error => {
            console.error(error);
        })

    }

  return (
    <div className='container'>
        <br /> <br />
        <div className='row'>
            <div className='col-md-6 offset-md-3'>
                <div className='card'>
                    <div className='card-header'>
                        <h2 className='text-center'> Login Form </h2>
                    </div>

                    <div className='card-body'>
                        <form>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Username or Email</label>
                                <div className='col-md-9'>
                                    <input
                                        type='text'
                                        name='username'
                                        className='form-control'
                                        placeholder='Enter username'
                                        value={username}
                                        onChange={ (e) => setUsername(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='row mb-3'>
                                <label className='col-md-3 control-label'> Password </label>
                                <div className='col-md-9'>
                                    <input
                                        type='password'
                                        name='password'
                                        className='form-control'
                                        placeholder='Enter password'
                                        value={password}
                                        onChange={ (e) => setPassword(e.target.value)}
                                    >
                                    </input>
                                </div>
                            </div>

                            <div className='form-group mb-3'>
                                <button className='btn btn-primary' onClick={ (e) => handleLoginForm(e)}>Submit</button>

                            </div>
                        </form>

                    </div>

                </div>
            </div>
        </div>


    </div>
  )
}

export default LoginComponent

Run the React App

Enter the URL http://localhost:3000/register in the browser, enter the details in the registration form, and check the response in the browser console.

React JS + Spring Boot Login and Registration Example

Enter the URL http://localhost:3000/login in the browser, enter the details in the login form, and check the response in the browser console.

React JS + Spring Boot Login and Registration Example

Comments