API
We will use a free Login API from MeCallAPI.com with the following detail:
- Method: POST
- URL: https://www.mecallapi.com/api/login
- Body (JSON):
{
"username": "karn.yong@mecallapi.com",
"password": "mecallapi"
}
- Response:
{
"status": "ok",
"message": "Logged in",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"fname": "Karn",
"lname": "Yong",
"username": "karn.yong@mecallapi.com",
"email": "karn.yong@mecallapi.com",
"avatar": "https://www.mecallapi.com/users/1.png"
}
}
For more APIs with populated fake data, such as user list and user profile authentication with JWT, these can be found at MeCallAPI.com.
Add packages
We will add the following packages to our application:
- Material UI
- react-router-dom
- Sweetalert
npm i @material-ui/core @material-ui/icons react-router-dom sweetalert
Create screen for Sign-in
Create Sigin.js (From line 41 is the use of login API from MeCallAPI.com)
import React, { useState } from 'react';
import swal from 'sweetalert';
import './Login.css';
async function loginUser(credentials) {
return fetch('https://www.mecallapi.com/api/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
const Login = props => {
const [username, setUserName] = useState();
const [password, setPassword] = useState();
const handleSubmit = async e => {
e.preventDefault();
const response = await loginUser({
username,
password
});
if ('accessToken' in response) {
swal("Success", response.message, "success", {
buttons: false,
timer: 2000,
})
.then((value) => {
localStorage.setItem('accessToken', response['accessToken']);
localStorage.setItem('user', JSON.stringify(response['user']));
window.location.href = "/admin";
});
} else {
swal("Failed", response.message, "error");
}
}
return (
<>
<div id="page-wrap" className="my-4 mx-4">
<h1>Login</h1>
<form noValidate onSubmit={handleSubmit}>
<div className="mb-3">
<label for="email" className="form-label">Email address</label>
<input
required
id="email"
name="email"
className="form-control"
aria-describedby="emailHelp"
onChange={e => setUserName(e.target.value)}
/>
</div>
<div className="mb-3">
<label for="password" className="form-label">Password</label>
<input
id="password"
name="password"
type="password"
className="form-control"
onChange={e => setPassword(e.target.value)}
/>
</div>
<div className="mb-3 form-check">
<input type="checkbox" className="form-check-input" id="exampleCheck1" />
<label className="form-check-label" for="exampleCheck1">Remember me</label>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
</div>
</>
)
}
export default Login;
Now you can update your menu to show correct menu items for logged in/out states:
import React, { lazy } from 'react';
import { Link } from 'react-router-dom';
import './Sidebar.css';
const Menu = lazy(() => import('react-burger-menu/lib/menus/elastic'));
const Sidebar = props => {
const isLoggedIn = localStorage.getItem('accessToken');
const handleLogout = () => {
localStorage.removeItem("accessToken");
localStorage.removeItem("user");
window.location.href = "/";
};
let adminLink, loggedLink;
if (isLoggedIn) {
adminLink = <Link className="menu-item" to="/admin">Admin</Link>;
loggedLink = <div className="menu-item" onClick={handleLogout}>Logout</div>;
} else {
loggedLink = <Link className="menu-item" to="/login">Login</Link>;
}
return (
<Menu>
<Link className="menu-item" to="/">
Home
</Link>
<Link className="menu-item" to="/favourites">
Favourites
</Link>
{adminLink}
{loggedLink}
</Menu>
);
}
export default Sidebar;