Basic React Login using External API

API

We will use a free Login API from MeCallAPI.com with the following detail:

{
    "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;

Leave a Reply

Your email address will not be published. Required fields are marked *