How to create React JS + PHP Login Registration System?

In this tutorial, you will learn how to create a simple Login and Registration System using the React JS, PHP, and MySQL Database.

The purpose of this tutorial is to give an idea of creating a Login and Registration system using React JS with Authorization REST API.

React JS + PHP Login Registration System
Demo of React JS + PHP Login and Registration System

Follow the below to create this React JS & PHP Login System

React JS is used to building user interfaces, so we can’t handle the backend with this. To interact with the backend, we will use the PHP RESTful API.

I have already made a tutorial on how to create PHP login & registration RESTful API. And in this tutorial, I will use that PHP RESTful API. So, you must first check out that.

After making the PHP RESTful API, set up your React CLI Environment & Install the Axios package to perform the ajax requests, and React Router V6 for routing.

npm install axios [email protected]

API URLs

POST - http://localhost/php-auth-api/register.php
POST - http://localhost/php-auth-api/login.php
GET - http://localhost/php-auth-api/getUser.php

Creating files & folders

Now we will create our application files and folders. But, before going further let’s take a look at the src folder structure. See the following image –

React PHP  login folder structure
UserContext.js

First, we will set up our app context. So inside the src folder create a new folder called context, and here we have to create the UserContext.js file.

import {createContext, useState, useEffect} from 'react'
import axios from 'axios'

export const UserContext = createContext();

export const Axios = axios.create({
    baseURL: 'http://localhost/php-auth-api/',
});

export const UserContextProvider = ({children}) => {

    const [theUser, setUser] = useState(null);
    const [wait, setWait] = useState(false);

    const registerUser = async ({name,email,password}) => {
        setWait(true);
        try{
            const {data} = await Axios.post('register.php',{
                name,
                email,
                password 
            });
            setWait(false);
            return data;
        }
        catch(err){
            setWait(false);
            return {success:0, message:'Server Error!'};
        }
    }

    const loginUser = async ({email,password}) => {
        setWait(true);
        try{
            const {data} = await Axios.post('login.php',{
                email,
                password 
            });
            if(data.success && data.token){
                localStorage.setItem('loginToken', data.token);
                setWait(false);
                return {success:1};
            }
            setWait(false);
            return {success:0, message:data.message};
        }
        catch(err){
            setWait(false);
            return {success:0, message:'Server Error!'};
        }

    }

    const loggedInCheck = async () => {
        const loginToken = localStorage.getItem('loginToken');
        Axios.defaults.headers.common['Authorization'] = 'Bearer '+loginToken;
        if(loginToken){
            const {data} = await Axios.get('getUser.php');
            if(data.success && data.user){
                setUser(data.user);
                return;
            }
            setUser(null);
        }
    }

    useEffect(() => {
        async function asyncCall(){
            await loggedInCheck();
        }
        asyncCall();
    },[]);

    const logout = () => {
        localStorage.removeItem('loginToken');
        setUser(null);
    }

    return (
        <UserContext.Provider value={{registerUser,loginUser,wait, user:theUser,loggedInCheck,logout}}>
            {children}
        </UserContext.Provider>
    );

}

export default UserContextProvider;

Creating Components

After creating the context file, Now we will create the app components. So, again inside the src folder create a new folder called components. And here we will create the app components.

  • Register.js – Where a user can Sign up.
  • Login.js – Where a user can log in.
  • Home.js – A user can access this page after login.
import {useContext, useState} from 'react'
import {Link} from 'react-router-dom'
import {UserContext} from '../context/UserContext';

const Register = () => {
    const {registerUser, wait} = useContext(UserContext);
    const [errMsg, setErrMsg] = useState(false);
    const [successMsg, setSuccessMsg] = useState(false);
    const [formData, setFormData] = useState({
        name:'',
        email:'',
        password:''
    });

    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]:e.target.value
        })
    }

    const submitForm = async (e) => {
        e.preventDefault();

        if(!Object.values(formData).every(val => val.trim() !== '')){
            setSuccessMsg(false);
            setErrMsg('Please Fill in all Required Fields!');
            return;
        }

        const data = await registerUser(formData);
        if(data.success){
            e.target.reset();
            setSuccessMsg('You have successfully registered.');
            setErrMsg(false);
        }
        else if(!data.success && data.message){
            setSuccessMsg(false);
            setErrMsg(data.message);
        }
        
    }

    return (
        <div className="myform">
            <h2>Sign Up</h2>
            <form onSubmit={submitForm}>
                <label htmlFor="name">Name:</label>
                <input type="text" name="name" onChange={onChangeInput} placeholder="Your name" id="name" value={formData.name} required />
                <label htmlFor="email">Email:</label>
                <input type="email" name="email" onChange={onChangeInput} placeholder="Your email" id="email" value={formData.email} required />
                <label htmlFor="password">Password:</label>
                <input type="password" name="password" onChange={onChangeInput} placeholder="New password" id="password" value={formData.password} required />
                {successMsg && <div className="success-msg">{successMsg}</div>}
                {errMsg && <div className="err-msg">{errMsg}</div>}
                <button type="submit" disabled={wait}>Sign Up</button>
                <div className="bottom-link"><Link to="/login">Login</Link></div>
            </form>
        </div>
    )
}

export default Register;
import {useState,useContext} from 'react';
import { Link } from 'react-router-dom';
import {UserContext} from '../context/UserContext';

const Login = () => {
    const {loginUser, wait, loggedInCheck} = useContext(UserContext);
    const [redirect, setRedirect] = useState(false);
    const [errMsg, setErrMsg] = useState(false);
    const [formData, setFormData] = useState({
        email:'',
        password:''
    });

    const onChangeInput = (e) => {
        setFormData({
            ...formData,
            [e.target.name]:e.target.value
        })
    }

    const submitForm = async (e) => {
        e.preventDefault();

        if(!Object.values(formData).every(val => val.trim() !== '')){
            setErrMsg('Please Fill in all Required Fields!');
            return;
        }

        const data = await loginUser(formData);
        if(data.success){
            e.target.reset();
            setRedirect('Redirecting...');
            await loggedInCheck();
            return;
        }
        setErrMsg(data.message);
    }

    return (
        <div className="myform">
            <h2>Login</h2>
            <form onSubmit={submitForm}>
                <label htmlFor="email">Email:</label>
                <input type="email" name="email" onChange={onChangeInput} placeholder="Your email" id="email" value={formData.email} required />
                <label htmlFor="password">Password:</label>
                <input type="password" name="password" onChange={onChangeInput} placeholder="New password" id="password" value={formData.password} required />
                {errMsg && <div className="err-msg">{errMsg}</div>}
                {redirect ? redirect : <button type="submit" disabled={wait}>Login</button>}
                <div className="bottom-link"><Link to="/signup">Sign Up</Link></div>
            </form>
        </div>
    )
}

export default Login;
import {useContext} from 'react'
import {UserContext} from '../context/UserContext'

const Home = () => {
    const {user, logout} = useContext(UserContext);
    return (
        <div className="home">
            <div className="img">🧒🏻</div>
            <h1>{user.name}<br/><span>{user.email}</span></h1>
            <button onClick={logout} className="logout">Logout</button>
        </div>
    )
}

export default Home;

App.js

Now inside the App.js file, we will define the components and routes.

import {useContext} from 'react'
import { BrowserRouter, Routes, Route, Navigate} from 'react-router-dom';
import {UserContext} from './context/UserContext';
import Login from './components/Login';
import Register from './components/Register';
import Home from './components/Home';

function App() {

  const {user} = useContext(UserContext); 
 
  return (
    <div className="container">
        <BrowserRouter>
          <Routes>
            { user && <Route path="/" element={<Home/>} /> }
            {!user && (
              <>
              <Route path="/login" element={<Login/>} />
              <Route path="/signup" element={<Register/>} />
              </>
            )}
            <Route path="*" element={<Navigate to={user ? '/':'/login'} />} />
          </Routes>
        </BrowserRouter>
    </div>
  );
}

export default App;

index.js

In the end, we need to define the Context Provider inside the index.js file.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import UserContextProvider from './context/UserContext';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <UserContextProvider>
      <App />
    </UserContextProvider>
  </React.StrictMode>,
  document.getElementById('root')
);

// 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();

index.css

Here is the stylesheet of this application –

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: #f2f2f2;
  padding: 20px;
  color: #222222;
}

input,
button {
  font-family: "Ubuntu", sans-serif;
  outline: none;
  font-size: 1rem;
}

.container {
  max-width: 600px;
  margin: 0 auto;
  background-color: white;
  padding: 20px;
  border-radius: 3px;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}

h2 {
  text-align: center;
  margin-top: 10px;
  text-transform: uppercase;
  font-size: 32px;
}

.myform {
  max-width: 400px;
  margin: 0 auto;
  padding: 20px 0 50px 0;
}

.myform form {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
}

.myform form label {
  font-weight: bold;
}

.myform form input {
  padding: 10px;
  font-size: 16px;
  border: 1px solid #bbbbbb;
  border-radius: 3px;
  margin-bottom: 5px;
}

.myform form input:hover {
  border-color: #999999;
}

.myform form input:focus {
  border-color: #0d6efd;
}

[type="submit"] {
  background: #0d6efd;
  color: white;
  border: 1px solid rgba(0, 0, 0, 0.175);
  border-radius: 3px;
  padding: 12px 0;
  cursor: pointer;
  box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
  margin-top: 5px;
  font-weight: bold;
  width: 100%;
}

[type="submit"]:disabled {
  background: #68a4fd;
}

[type="submit"]:disabled:hover {
  box-shadow: none;
}


.success-msg,
.err-msg {
  color: #dc3545;
  border: 1px solid #dc3545;
  padding: 10px;
  border-radius: 3px;
}

.success-msg {
  color: #ffffff;
  background-color: #20c997;
  border-color: rgba(0, 0, 0, 0.1);
}

.bottom-link {
  text-align: center;
  padding-top: 10px;
}

.home {
  text-align: center;
}

.home .img {
  font-size: 100px;
}

.home h1 span {
  font-weight: normal;
  font-size: 16px;
}

button.logout {
  background: #dc3545;
  border: 1px solid rgba(0, 0, 0, .3);
  padding: 10px 15px;
  color: white;
  cursor: pointer;
  border-radius: 3px;
}

button.logout:hover,
[type="submit"]:hover {
  box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}

Now time to test it. To test this application, execute the npm start command in your terminal.

5 Comments

  1. Hello Bro,
    Can you please help me to merge login & registration system and crud with reactjs PHP MySQL as single application.

Leave a Reply