Contents
Hi there, today we will show you how to develop login and registration in ReactJS app using API. Most of the web apps today that have users or different types of users require login or authentication to safeguard the functionalities and data information of the system. And today, I will show you how to make a user login and registration in ReactJS.
React or also called React.js or Reactjs is a free and open-source JavaScript library used for building user interfaces(UI). It is one of the most popular JavaScript libraries for building the front end. React is created by Facebook and maintained by Facebook.
In this tutorial, we will be using the API available that is made by Binaryboxtus. you can check it out here.
Prerequisite:
- npm >= 7.24.0
- node >= v16.10.0
- npx >= 7.24.0
Step 1: Create A React App
First, select a folder that you want the React App to be created then execute this command on Terminal or CMD to create the React App:
npx create-react-app react-login-register
Step 2: Install packages
After creating a fresh react project, go to the react project folder and install these packages:
- react-router-dom – a package used for client-side routing that allows the app to change the URL without making another request for a document from the server but instead it will immediately render the new UI or new information.
- bootstrap – a package of bootstrap framework
- axios – a promised-based HTTP library that is used to request to a server or API.
npm i bootstrap
npm i react-router-dom
npm i axios
Step 3: Create .env
After installing the packages, we will now create our .env file on our root directory. We will declare the API base URL and API Key in the .env file. Don’t forget to add it to the .gitignore file.
You can get the REACT_APP_API_KEY here. Click the “Reveal Key” button and copy the API key.
.env
REACT_APP_API_URL="https://mock-api.binaryboxtuts.com/"
REACT_APP_API_KEY="put_the_api_key_here"
Step 4: Routing and Components
We will now create the component, refer to the image below for the file structure.
You can create your own file structure but for this tutorial just follow along.
Let’s update the App.js file – We will add the routes here:
src/App.js
import React from 'react'
import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
import Login from "./pages/Login"
import Register from "./pages/Register"
import Dashboard from "./pages/Dashboard"
function App() {
return (
<Router>
<Routes>
<Route exact path="/" element={<Login/>} />
<Route path="/register" element={<Register/>} />
<Route path="/dashboard" element={<Dashboard/>} />
</Routes>
</Router>
);
}
export default App;
Let’s update the index.js file – We will add the axios base URL and add the API Key on the axios header.
src/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.css';
import axios from 'axios';
const root = ReactDOM.createRoot(document.getElementById('root'));
axios.defaults.baseURL = process.env.REACT_APP_API_URL
axios.interceptors.request.use(function (config) {
config.headers['X-Binarybox-Api-Key'] = process.env.REACT_APP_API_KEY;
return config;
});
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();
Let’s create a new directory /src/components. Inside the directory, let’s create a file named Layout.js – this will serve as a template.
src/components/Layout.js
import React from 'react'
const Layout =({children}) =>{
return(
<div className="container">{children}</div>
)
}
export default Layout;
We will now create a directory src/pages. Inside the folder let’s create these files for our pages:
- Dashboard.js
- Login.js
- Register.js
src/pages/Dashboard.js
import React,{ useEffect, useState } from 'react'
import axios from 'axios'
import { useNavigate } from "react-router-dom"
import Layout from "../components/Layout"
function Dashboard() {
const navigate = useNavigate();
const [user, setUser] = useState({})
useEffect(()=>{
if(localStorage.getItem('token') == "" || localStorage.getItem('token') == null){
navigate("/");
}else {
getUser()
}
},[])
const getUser = () => {
axios.get('/api/user', { headers:{Authorization: 'Bearer ' + localStorage.getItem('token')}})
.then((r) => {
setUser(r.data)
})
.catch((e) => {
console.log(e)
});
}
const logoutAction = () => {
axios.post('/api/logout',{}, { headers:{Authorization: 'Bearer ' + localStorage.getItem('token')}})
.then((r) => {
localStorage.setItem('token', "")
navigate("/");
})
.catch((e) => {
console.log(e)
});
}
return (
<Layout>
<div className="row justify-content-md-center">
<div className="col-12">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<div className="container-fluid">
<a className="navbar-brand" href="#">Dashboard</a>
<div className="d-flex">
<ul className="navbar-nav">
<li className="nav-item">
<a onClick={()=>logoutAction()} className="nav-link " aria-current="page" href="#">Logout</a>
</li>
</ul>
</div>
</div>
</nav>
<h2 className="text-center mt-5">Welcome, {user.name}!</h2 >
</div>
</div>
</Layout>
);
}
export default Dashboard;
src/pages/Login.js
import React,{ useEffect, useState } from 'react'
import axios from 'axios'
import { Link, useNavigate } from "react-router-dom"
import Layout from "../components/Layout"
function Login() {
const navigate = useNavigate();
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [validationErrors, setValidationErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(()=>{
if(localStorage.getItem('token') != "" && localStorage.getItem('token') != null){
navigate("/dashboard");
}
console.log(localStorage.getItem('token'))
},[])
const loginAction = (e) => {
setValidationErrors({})
e.preventDefault();
setIsSubmitting(true)
let payload = {
email:email,
password:password,
}
axios.post('/api/login', payload)
.then((r) => {
setIsSubmitting(false)
localStorage.setItem('token', r.data.token)
navigate("/dashboard");
})
.catch((e) => {
setIsSubmitting(false)
if (e.response.data.errors != undefined) {
setValidationErrors(e.response.data.errors);
}
if (e.response.data.error != undefined) {
setValidationErrors(e.response.data.error);
}
});
}
return (
<Layout>
<div className="row justify-content-md-center mt-5">
<div className="col-4">
<div className="card">
<div className="card-body">
<h5 className="card-title mb-4">Sign In</h5>
<form onSubmit={(e)=>{loginAction(e)}}>
{Object.keys(validationErrors).length != 0 &&
<p className='text-center '><small className='text-danger'>Incorrect Email or Password</small></p>
}
<div className="mb-3">
<label
htmlFor="email"
className="form-label">
Email address
</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={email}
onChange={(e)=>{setEmail(e.target.value)}}
/>
</div>
<div className="mb-3">
<label
htmlFor="password"
className="form-label">Password
</label>
<input
type="password"
className="form-control"
id="password"
name="password"
value={password}
onChange={(e)=>{setPassword(e.target.value)}}
/>
</div>
<div className="d-grid gap-2">
<button
disabled={isSubmitting}
type="submit"
className="btn btn-primary btn-block">Login</button>
<p className="text-center">Don't have account? <Link to="/register">Register here</Link></p>
</div>
</form>
</div>
</div>
</div>
</div>
</Layout>
);
}
export default Login;
src/pages/Register.js.
import React,{ useState, useEffect } from 'react'
import axios from 'axios'
import { Link, useNavigate } from "react-router-dom"
import Layout from "../components/Layout"
function Register() {
const navigate = useNavigate();
const [name, setName] = useState("")
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
const [confirmPassword, setConfirmPassword] = useState("")
const [validationErrors, setValidationErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(()=>{
if(localStorage.getItem('token') != "" && localStorage.getItem('token') != null){
navigate("/dashboard");
}
},[])
const registerAction = (e) => {
e.preventDefault();
setIsSubmitting(true)
let payload = {
name: name,
email:email,
password:password,
password_confirmation:confirmPassword
}
axios.post('/api/register', payload)
.then((r) => {
setIsSubmitting(false)
localStorage.setItem('token', r.data.token)
navigate("/dashboard");
})
.catch((e) => {
setIsSubmitting(false)
if (e.response.data.errors != undefined) {
setValidationErrors(e.response.data.errors);
}
});
}
return (
<Layout>
<div className="row justify-content-md-center mt-5">
<div className="col-4">
<div className="card">
<div className="card-body">
<h5 className="card-title mb-4">Register</h5>
<form onSubmit={(e)=>registerAction(e)}>
<div className="mb-3">
<label
htmlFor="name"
className="form-label">Name
</label>
<input
type="text"
className="form-control"
id="name"
name="name"
value={name}
onChange={(e)=>{setName(e.target.value)}}
/>
{validationErrors.name != undefined &&
<div className="flex flex-col">
<small className="text-danger">
{validationErrors.name[0]}
</small >
</div>
}
</div>
<div className="mb-3">
<label
htmlFor="email"
className="form-label">Email address
</label>
<input
type="email"
className="form-control"
id="email"
name="email"
value={email}
onChange={(e)=>{setEmail(e.target.value)}}
/>
{validationErrors.email != undefined &&
<div className="flex flex-col">
<small className="text-danger">
{validationErrors.email[0]}
</small >
</div>
}
</div>
<div className="mb-3">
<label
htmlFor="password"
className="form-label">Password
</label>
<input
type="password"
className="form-control"
id="password"
name="password"
value={password}
onChange={(e)=>setPassword(e.target.value)}
/>
{validationErrors.password != undefined &&
<div className="flex flex-col">
<small className="text-danger">
{validationErrors.password[0]}
</small >
</div>
}
</div>
<div className="mb-3">
<label
htmlFor="confirm_password"
className="form-label">Confirm Password
</label>
<input
type="password"
className="form-control"
id="confirm_password"
name="confirm_password"
value={confirmPassword}
onChange={(e)=>setConfirmPassword(e.target.value)}
/>
</div>
<div className="d-grid gap-2">
<button
disabled={isSubmitting}
type="submit"
className="btn btn-primary btn-block">Register Now
</button>
<p
className="text-center">Have already an account <Link to="/">Login here</Link>
</p>
</div>
</form>
</div>
</div>
</div>
</div>
</Layout>
);
}
export default Register;
Step 5: Run the app
We’re all done, what is left is to run the app.
npm start
Open this URL:
http://localhost:3000
Screenshots:
Login Page
Register Page
Dashboard Page