This series of articles discusses how to use Laravel Sanctum to provide authentication for a front end React application. In part one, I outlined the steps required to build and configure the Laravel back end. In this article, we turn our attention to the React front end. I will be focussing on the areas that are unique to this application, namely the communication between React on the client and Laravel on the server. I am assuming that you already have the basic skills needed to build a React app.
For additional reference, there is a live version of the finished app as well as complete code listings for the React client application and the Laravel server application.
Creating a React Project
To get started, create a new project named react-auth with create-react-app.
npx create-react-app react-auth
Then add axios, which will be used to make XMLHttpRequests to the Laravel API from the browser.
cd c:/react-auth
npm install axios
Styling with TailwindCSS
There are different approaches for styling React components. I'm a big fan of TailwindCSS, which can be installed like this.
npm install tailwindcss
Next, create a configuration file named tailwind.config.js by using the following command.
npx tailwind init
In the root directory of the application, manually create a file named style.css. Along with tailwind.config.js, this file can be used to customize Tailwind. Initially, the file should look like this.
@tailwind base;
@tailwind components;
@tailwind utilities;
If you'd like, you can make any changes you want to tailwind.config.js and style.css. Whether you make any customizations or not, you have to run a build step that creates the actual css file used that will be used by the application.
npx tailwind build style.css -o src/css/tailwind.css
Finally, make the styles available to our components by importing tailwind.css into App.js.
import "./css/tailwind.css"
Icons
The forms in my application make use of a number of different icons. It's easy to include them by using React Icons.
npm install react-icons --save
And with this, all of the dependencies have now been installed.
App Overview
Let's take a look at how the app is going to work. It begins by displaying the following splash screen.
There's a menu on the right side for choosing between
Signup - allowing first time users to register, and
Login - allowing restistered users to access the application.
To signup, the user enters a user name, email address, and password.
Previously registered users can login with email and password.
A logged in user can then logout.
After the user has logged out, the app will once again display the opening splash screen. There's nothing unusual or surprising here. This is the standard authentication sequence that everyone is more than familiar with.
State Management
Let's take a look at the state that's required to implement this process. This application is going to use React Context for managing the state. The context is defined in the contexts/AppContext.js file.
The main components of the state are:
authStatus - Used to control which component is visible at any particular time. As the user proceeds through each step of authentication, this value is changed so that the next component will be displayed.
User information (userId and userName). userId is the key that can be used by the Laravel backend to retrieve user information from the database. There's really no use for it in this simple authentication application, but userId would be an important piece of information in almost any project that's going to work with a real backend API.
Form information (userNameInput, userEmail, and userPassword) These are the items that will be obtained from the forms and passed to Laravel to perform the authentication functions.
Code Organization
The App.js file for the application looks like this.
import React from "react"
import "./css/tailwind.css"
import { AppProvider } from "./contexts/AppContext"
import AuthContainer from "./components/AuthContainer"
function App() {
return (
<div className="flex w-full justify-center bg-blue-200 pt-16 pb-32">
<div className="lg:flex w-11/12 lg:w-3/4 xl:w-3/5">
<AppProvider>
<AuthContainer />
</AppProvider>
</div>
</div>
)
}
export default App
App.js is basically just an AuthContainer component wrapped in an AppProvider component. AuthContainer is used to hold all the form components (splash screen, signup, login, logout) along with the logic needed to display the correct one at the appropriate time. AppProvider is needed so that the rest of the components can have access to the state by way of the context.
Here is the components/AuthContainer.js file.
import React, { useContext } from "react"
import {
NOT_LOGGED_IN,
LOG_IN_FORM,
SIGN_UP_FORM,
LOGGED_IN,
} from "../constants/AuthStatus"
import AuthNotLoggedIn from "./AuthNotLoggedIn"
import AuthSignup from "./AuthSignup"
import AuthLogin from "./AuthLogin"
import AuthLogout from "./AuthLogout"
import { AppContext } from "../contexts/AppContext"
const AuthContainer = () => {
const appContext = useContext(AppContext)
const { authStatus } = appContext
const showNotLoggedIn = authStatus === NOT_LOGGED_IN ? "" : "hidden"
const showLoginForm = authStatus === LOG_IN_FORM ? "" : "hidden"
const showSignupForm = authStatus === SIGN_UP_FORM ? "" : "hidden"
const showLoggedIn = authStatus === LOGGED_IN ? "" : "hidden"
return (
<div className="w-full">
<div className={showNotLoggedIn + " justify-end py-4"}>
<AuthNotLoggedIn />
</div>
<div className={showLoginForm + " justify-end py-4"}>
<AuthLogin option="login" />
</div>
<div className={showSignupForm + " justify-end py-4"}>
<AuthSignup option="signup" />
</div>
<div className={showLoggedIn + " justify-end py-4"}>
<AuthLogout />
</div>
</div>
)
}
export default AuthContainer
The following lines of code give the component access to the state in the context.
import React, { useContext } from "react";
import { AppContext } from "../contexts/AppContext";
const AuthContainer = () => {
const appContext = useContext(AppContext);
const { authStatus } = appContext;
AuthContainer just has one job. It reads the current status from the state authStatus variable, and then based on that value it shows the appropriate component to the user. All of the components are in the src/components folder.
Splash Screen
When the app begins, authStatus is initialized to NOT_LOGGED_IN, causing the splash screen from the component AuthNotLoggedIn to be made visible. AuthNotLoggedIn contains two components. The first is an illustration created by Katerina Limpitsouni and made freely available at her website unDraw. The second is the AuthMenu component, which is also used in the signup and login displays. AuthMenu has two buttons.
When the Signup button is clicked, the changeAuthStatusSignup() function in AppContext.js is run, and the value of authStatus is changed to SIGN_UP_FORM. This causes the current display to be hidden and the AuthSignup component to be made visible.
When the Login button is clicked, the changeAuthStatusLogin() function in AppContext.js is run, and the value of authStatus is changed to LOG_IN_FORM. This causes the current display to be hidden and the AuthLogin component to be made visible.
Part 3
This article has outlined how the user interface part of our React application works. In Part 3, we'll take a look at what happens when the user fills in the login form and presses the submit button, initiating communications between the React front end and the Laravel back end.
Top comments (5)
You are missing lots of things while write the article. I barely think a newbie will be able to follow the article and implement what you are trying to teach.
If you have any specific questions, I would be happy to try to answer them. However, authentication is not a topic for beginners. You should be comfortable building both React front end applications and Laravel back end applications before attempting to understand Sanctum. Best of luck with your studies!
I am not a newbie. I am a professional Laravel developer.
I went through your article and found so many things missing. I also have written multiple articles hoping to help the developers and newbies.
When you are making a tutorial or writing an article it's our duty and responsibility to present everything so that the one who is following your article does not feel that s/he is missing out something.
You have missed so many things in the articles. So I suggest you please revisit your article again and make the necessary changes. It will help many other people who are willing to learn many things.
Best of luck with future articles.
I did not mean to disparage your level of experience. You said "I barely think a newbie will be able to follow the article" so I addressed my comments to that.
I would like to help but I don't understand. What are the things that you feel are missing?
The missing piece to me is there is not status indicating that user has logged in if he reloads the page.
How to implement that if using cookie-based authentication?