React When Login Change the Navigation Bar State Updated FREE

React When Login Change the Navigation Bar State

In this tutorial, nosotros're gonna build a React Redux Login, Logout, Registration case with LocalStorage, React Router, Axios and Bootstrap using React.js Hooks. I will evidence y'all:

  • JWT Hallmark Menstruum for User Registration & User Login, Logout
  • Project Structure for React Redux JWT Hallmark, LocalStorage, Router, Axios
  • Working with Redux Actions, Reducers, Store for Awarding land
  • Creating React Office Components with Hooks & Course Validation
  • React Role Components for accessing protected Resources (Authorisation)
  • Dynamic Navigation Bar in React App

Related Posts:
– In-depth Introduction to JWT-JSON Web Token
– React Hooks Grime example with Axios and Spider web API
– React Hooks File Upload example with Axios & Progress Bar
– React Form Validation with Hooks example

Fullstack (JWT Hallmark & Potency example):
– React + Spring Kicking
– React + Node.js Express

The example without using Hooks (but React Components):
React Redux Login, Logout, Registration instance

The case without using Redux:
React Hooks: JWT Authentication (without Redux) example

Overview of React Redux Registration & Login instance

We will build a React.js application using Hooks in that:

  • At that place are Login/Logout, Signup pages.
  • Form data will be validated by front-end before beingness sent to back-end.
  • Depending on User'south roles (admin, moderator, user), Navigation Bar changes its items automatically.

Hither are the screenshots:
– Registration Page:

react-redux-login-registration-example-signup

– Signup failed:

react-redux-login-registration-example-signup-email-duplicate

– Grade Validation Back up:

react-redux-login-registration-example-form-validation

If you demand Form Validation with React Hook Course 7, delight visit:
React Form Validation with Hooks example

– Login Page:

react-redux-login-registration-example-login

– Profile Page (for successful Login):

react-redux-login-registration-example-login-success-profile-page

– For Moderator account login, the navigation bar will change by authorities:

react-redux-login-registration-example-authorization-login

– Check Browser Local Storage:

react-redux-login-registration-example-local-storage

– Bank check State in Redux using redux-devtools-extension:

react-redux-login-registration-example-redux-devtools-extension

If you lot want to add together refresh token, delight visit:
React + Redux: Refresh Token with Axios and JWT example

User Registration and User Login Menstruum

For JWT Hallmark, we're gonna telephone call 2 endpoints:

  • POST api/auth/signup for User Registration
  • POST api/auth/signin for User Login

The post-obit flow shows you an overview of Requests and Responses that React.js Customer will make or receive. This React Client must add a JWT to HTTP Header before sending request to protected resources.

react-redux-login-registration-example-flow

Y'all can detect step by step to implement these back-end servers in following tutorial:

  • Spring Kicking JWT Hallmark with Spring Security, MySQL
  • Jump Kick JWT Hallmark with Bound Security, PostgreSQL
  • Jump Boot JWT Authentication with Bound Security, MongoDB
  • Node.js JWT Hallmark & Say-so with MySQL
  • Node.js JWT Authentication & Authorisation with PostgreSQL
  • Node.js JWT Authentication & Say-so with MongoDB

React Component Diagram with Redux, Router, Axios

Let's look at the diagram below.

react-redux-login-registration-example-project-overview

– The App page is a container with React Router. It gets app country from Redux Store. Then the navbar now can display based on the state.

Login & Annals pages have form for information submission (with support of react-validation library). They dispatch auth deportment (login/register) to Redux Thunk Middleware which uses auth.service to phone call API.

auth.service methods utilize axios to brand HTTP requests. Its as well store or get JWT from Browser Local Storage inside these methods.

Dwelling folio is public for all visitor.

Contour page displays user information afterwards the login action is successful.

BoardUser, BoardModerator, BoardAdmin pages will be displayed in navbar by land user.roles. In these pages, we use user.service to access protected resources from Web API.

user.service uses auth-header() helper function to add JWT to HTTP header. auth-header() returns an object containing the JWT of the currently logged in user from Local Storage.

Technology

Nosotros're gonna use these modules:

  • React 16
  • react-redux 7.2.i
  • redux iv.0.5
  • redux-thunk 2.iii.0
  • react-router-dom v
  • axios 0.nineteen.2
  • react-validation 3.0.7
  • Bootstrap 4
  • validator 13.1.1

Project Structure

This is folders & files structure for this React Redux Registration and Login application:

react-redux-login-registration-example-project-structure

With the explanation in diagram higher up, yous can understand the project construction easily.

But I need to say some things about Redux elements that we're gonna use:
actions folder contains all the action creators (auth.js for annals & login, message.js for response message from server).
reducers folder contains all the reducers, each reducer updates a unlike role of the application country corresponding to dispatched action.

If yous want to apply redux-toolkit instead, please visit:
React Redux Login, Register example with redux-toolkit & Hooks

Setup React.js Project

Open cmd at the folder you want to save Project folder, run command:
npx create-react-app react-redux-hooks-jwt-auth

So add Router Dom Module for after use: npm install react-router-dom.

Import Bootstrap

Run command: npm install bootstrap.

Open src/App.js and modify the code within it as following-

          import React from "react"; import "bootstrap/dist/css/bootstrap.min.css"; const App = () => {   // ... } export default App;                  

Create Services

We're gonna create ii services in src/services folder:

  • Authentication service
  • Data service

services

auth-header.js

auth.service.js (Authentication service)

user.service.js (Data service)


Before working with these services, nosotros need to install Axios with command:
npm install axios

Hallmark service

The service uses Axios for HTTP requests and Local Storage for user information & JWT.
It provides following important functions:

  • register(): POST {username, electronic mail, password}
  • login(): POST {username, countersign} & save JWT to Local Storage
  • logout(): remove JWT from Local Storage

services/auth.service.js

          import axios from "axios"; const API_URL = "http://localhost:8080/api/auth/"; const register = (username, email, password) => {   render axios.post(API_URL + "signup", {     username,     electronic mail,     password,   }); }; const login = (username, password) => {   render axios     .post(API_URL + "signin", {       username,       password,     })     .so((response) => {       if (response.information.accessToken) {         localStorage.setItem("user", JSON.stringify(response.information));       }       return response.information;     }); }; const logout = () => {   localStorage.removeItem("user"); }; export default {   register,   login,   logout, };                  

Information service

We also accept methods for retrieving data from server. In the instance we access protected resources, the HTTP request needs Say-so header.

Let'due south create a helper part chosen authHeader() inside auth-header.js:

          export default function authHeader() {   const user = JSON.parse(localStorage.getItem('user'));   if (user && user.accessToken) {     return { Dominance: 'Bearer ' + user.accessToken };   } else {     render {};   } }                  

The lawmaking higher up checks Local Storage for user item. If there is a logged in user with accessToken (JWT), return HTTP Authority header. Otherwise, return an empty object.


Note: For Node.js Express dorsum-end, please employ x-access-token header like this:

          consign default function authHeader() {   const user = JSON.parse(localStorage.getItem('user'));   if (user && user.accessToken) {     // for Node.js Express back-end     return { '10-access-token': user.accessToken };   } else {     return {};   } }                  

Now we define a service for accessing data in services/user.service.js:

          import axios from "axios"; import authHeader from "./auth-header"; const API_URL = "http://localhost:8080/api/test/"; const getPublicContent = () => {   return axios.become(API_URL + "all"); }; const getUserBoard = () => {   return axios.go(API_URL + "user", { headers: authHeader() }); }; const getModeratorBoard = () => {   return axios.go(API_URL + "modern", { headers: authHeader() }); }; const getAdminBoard = () => {   render axios.get(API_URL + "admin", { headers: authHeader() }); }; export default {   getPublicContent,   getUserBoard,   getModeratorBoard,   getAdminBoard, };                  

You can run across that we add together a HTTP header with the assistance of authHeader() office when requesting authorized resources.

Create Redux Deportment

We're gonna create 2 kind of actions in src/actions folder:


actions

types.js

auth.js (annals/login/logout actions)

message.js (set/clear message actions)


Action Types

First we defined some string constant that indicates the type of action being performed.

actions/blazon.js

          export const REGISTER_SUCCESS = "REGISTER_SUCCESS"; export const REGISTER_FAIL = "REGISTER_FAIL"; export const LOGIN_SUCCESS = "LOGIN_SUCCESS"; export const LOGIN_FAIL = "LOGIN_FAIL"; export const LOGOUT = "LOGOUT"; consign const SET_MESSAGE = "SET_MESSAGE"; export const CLEAR_MESSAGE = "CLEAR_MESSAGE";                  

Message Actions Creator

This Redux action creator is for actions related to messages (notifications) from APIs.

actions/bulletin.js

          import { SET_MESSAGE, CLEAR_MESSAGE } from "./types"; export const setMessage = (bulletin) => ({   blazon: SET_MESSAGE,   payload: message, }); export const clearMessage = () => ({   type: CLEAR_MESSAGE, });                  

Auth Actions Creator

This is creator for deportment related to authentication. Nosotros're gonna import AuthService to make asynchronous HTTP requests with trigger one or more than dispatch in the outcome.

register()

  • calls the AuthService.register(username, e-mail, password)
  • dispatch REGISTER_SUCCESS and SET_MESSAGE if successful
  • dispatch REGISTER_FAIL and SET_MESSAGE if failed

login()

  • calls the AuthService.login(username, countersign)
  • dispatch LOGIN_SUCCESS and SET_MESSAGE if successful
  • acceleration LOGIN_FAIL and SET_MESSAGE if failed

Both action creators return a Hope for Components using them.

actions/auth.js

          import {   REGISTER_SUCCESS,   REGISTER_FAIL,   LOGIN_SUCCESS,   LOGIN_FAIL,   LOGOUT,   SET_MESSAGE, } from "./types"; import AuthService from "../services/auth.service"; export const annals = (username, e-mail, password) => (dispatch) => {   return AuthService.annals(username, email, password).and then(     (response) => {       dispatch({         blazon: REGISTER_SUCCESS,       });       dispatch({         type: SET_MESSAGE,         payload: response.data.message,       });       return Hope.resolve();     },     (error) => {       const bulletin =         (error.response &&           error.response.data &&           error.response.data.message) ||         error.message ||         fault.toString();       dispatch({         type: REGISTER_FAIL,       });       dispatch({         type: SET_MESSAGE,         payload: message,       });       return Promise.pass up();     }   ); }; consign const login = (username, countersign) => (acceleration) => {   render AuthService.login(username, countersign).then(     (data) => {       dispatch({         type: LOGIN_SUCCESS,         payload: { user: data },       });       return Promise.resolve();     },     (fault) => {       const message =         (error.response &&           error.response.data &&           error.response.information.message) ||         mistake.message ||         error.toString();       dispatch({         type: LOGIN_FAIL,       });       dispatch({         type: SET_MESSAGE,         payload: message,       });       return Hope.reject();     }   ); }; consign const logout = () => (dispatch) => {   AuthService.logout();   dispatch({     type: LOGOUT,   }); };                  

Create Redux Reducers

There will exist two reducers in src/reducers binder, each reducer updates a different part of the state corresponding to dispatched Redux actions.


reducers

index.js

auth.js (register/login/logout)

message.js (set/clear message)


Message Reducer

This reducer updates message land when message action is dispatched from anywhere in the application.

reducers/message.js

          import { SET_MESSAGE, CLEAR_MESSAGE } from "../actions/types"; const initialState = {}; consign default function (state = initialState, activity) {   const { blazon, payload } = action;   switch (type) {     example SET_MESSAGE:       render { message: payload };     case CLEAR_MESSAGE:       render { message: "" };     default:       return state;   } }                  

Auth Reducer

The Auth reducer will update the isLoggedIn and user state of the awarding.

reducers/auth.js

          import {   REGISTER_SUCCESS,   REGISTER_FAIL,   LOGIN_SUCCESS,   LOGIN_FAIL,   LOGOUT, } from "../actions/types"; const user = JSON.parse(localStorage.getItem("user")); const initialState = user   ? { isLoggedIn: true, user }   : { isLoggedIn: imitation, user: null }; export default part (state = initialState, action) {   const { type, payload } = action;   switch (type) {     case REGISTER_SUCCESS:       return {         ...state,         isLoggedIn: imitation,       };     case REGISTER_FAIL:       return {         ...state,         isLoggedIn: false,       };     instance LOGIN_SUCCESS:       return {         ...state,         isLoggedIn: true,         user: payload.user,       };     case LOGIN_FAIL:       return {         ...state,         isLoggedIn: fake,         user: cypher,       };     case LOGOUT:       return {         ...state,         isLoggedIn: simulated,         user: null,       };     default:       render state;   } }                  

Combine Reducers

Because nosotros merely have a single store in a Redux application. We use reducer composition instead of many stores to split data handling logic.

reducers/alphabetize.js

          import { combineReducers } from "redux"; import auth from "./auth"; import bulletin from "./message"; export default combineReducers({   auth,   bulletin, });                  

Create Redux Store

This Store volition bring Deportment and Reducers together and hold the Application country.

Now nosotros demand to install Redux, Thunk Middleware and Redux Devtool Extension.
Run the control:

          npm install redux redux-thunk npm install --relieve-dev redux-devtools-extension                  

In the previous section, we used combineReducers() to combine 2 reducers into ane. Let'due south import it, and laissez passer information technology to createStore():

shop.js

          import { createStore, applyMiddleware } from "redux"; import { composeWithDevTools } from "redux-devtools-extension"; import thunk from "redux-thunk"; import rootReducer from "./reducers"; const middleware = [thunk]; const store = createStore(   rootReducer,   composeWithDevTools(applyMiddleware(...middleware)) ); export default store;                  

Create React Pages for Authentication

In src folder, create new folder named components and add several files as following:


components

Login.js

Register.js

Profile.js


Form Validation overview

Now nosotros need a library for Form validation, so we're gonna add react-validation library to our project.
Run the control: npm install react-validation validator

To use react-validation in this example, yous need to import post-obit items:

          import Form from "react-validation/build/form"; import Input from "react-validation/build/input"; import CheckButton from "react-validation/build/button"; import { isEmail } from "validator";                  

Nosotros besides utilise isEmail() function from validator to verify email.

This is how we put them in render() method with validations attribute:

          const required = value => {   if (!value) {     render (       <div className="warning alert-danger" part="alert">         This field is required!       </div>     );   } }; const email = value => {   if (!isEmail(value)) {     render (       <div className="alert alert-danger" role="alert">         This is non a valid e-mail.       </div>     );   } }; render() {   return (   ...     <Form       onSubmit={handleLogin}       ref={form}     >       ...       <Input         type="text"         className="grade-control"         ...         validations={[required, email]}       />       <CheckButton         mode={{ brandish: "none" }}         ref={checkBtn}       />     </Form>   ...   ); }                  

We're gonna call Form validateAll() method to check validation functions in validations. And then CheckButton helps us to verify if the form validation is successful or not. And then this button will not display on the form.

          grade.validateAll(); if (checkBtn.context._errors.length === 0) {   // practise something when no error }                  

If you need Form Validation with React Claw Course 7, please visit:
React Form Validation with Hooks example

Login Page

This page has a Form with username & password.
– We're gonna verify them every bit required field.
– If the verification is ok, nosotros dispatch login activity, then direct user to Profile page: props.history.push("/profile");, or show bulletin with response mistake.

For getting the awarding land and dispatching actions, we apply React Redux Hooks useSelector and useDispatch.
– past checking isLoggedIn, we tin redirect user to Profile page.
message gives us response message.

components/Login.js

          import React, { useState, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Redirect } from 'react-router-dom'; import Form from "react-validation/build/form"; import Input from "react-validation/build/input"; import CheckButton from "react-validation/build/button"; import { login } from "../actions/auth"; const required = (value) => {   if (!value) {     render (       <div className="alert alert-danger" part="alert">         This field is required!       </div>     );   } }; const Login = (props) => {   const class = useRef();   const checkBtn = useRef();   const [username, setUsername] = useState("");   const [password, setPassword] = useState("");   const [loading, setLoading] = useState(false);   const { isLoggedIn } = useSelector(country => state.auth);   const { bulletin } = useSelector(state => country.message);   const dispatch = useDispatch();   const onChangeUsername = (e) => {     const username = e.target.value;     setUsername(username);   };   const onChangePassword = (e) => {     const password = east.target.value;     setPassword(password);   };   const handleLogin = (due east) => {     e.preventDefault();     setLoading(true);     course.current.validateAll();     if (checkBtn.electric current.context._errors.length === 0) {       dispatch(login(username, countersign))         .then(() => {           props.history.push("/profile");           window.location.reload();         })         .catch(() => {           setLoading(simulated);         });     } else {       setLoading(false);     }   };   if (isLoggedIn) {     return <Redirect to="/contour" />;   }   return (     <div className="col-md-12">       <div className="carte card-container">         <img           src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"           alt="contour-img"           className="profile-img-carte du jour"         />         <Form onSubmit={handleLogin} ref={form}>           <div className="course-group">             <label htmlFor="username">Username</label>             <Input               blazon="text"               className="form-control"               name="username"               value={username}               onChange={onChangeUsername}               validations={[required]}             />           </div>           <div className="form-grouping">             <label htmlFor="countersign">Password</label>             <Input               type="password"               className="grade-command"               name="password"               value={password}               onChange={onChangePassword}               validations={[required]}             />           </div>           <div className="course-group">             <button className="btn btn-primary btn-block" disabled={loading}>               {loading && (                 <span className="spinner-edge spinner-edge-sm"></span>               )}               <bridge>Login</span>             </button>           </div>           {bulletin && (             <div className="form-group">               <div className="alert warning-danger" role="alert">                 {message}               </div>             </div>           )}           <CheckButton manner={{ display: "none" }} ref={checkBtn} />         </Form>       </div>     </div>   ); }; export default Login;                  

Register Page

This page is similar to Login Folio.

For Course Validation, at that place are some more details:

  • username: required, between 3 and xx characters
  • email: required, email format
  • password: required, between six and 40 characters

Nosotros're gonna dispatch register activeness and bear witness response bulletin (successful or error).

components/Register.js

          import React, { useState, useRef } from "react"; import { useDispatch, useSelector } from "react-redux"; import Course from "react-validation/build/grade"; import Input from "react-validation/build/input"; import CheckButton from "react-validation/build/push button"; import { isEmail } from "validator"; import { register } from "../actions/auth"; const required = (value) => {   if (!value) {     return (       <div className="alert alarm-danger" role="alert">         This field is required!       </div>     );   } }; const validEmail = (value) => {   if (!isEmail(value)) {     render (       <div className="alert alert-danger" office="alarm">         This is non a valid email.       </div>     );   } }; const vusername = (value) => {   if (value.length < 3 || value.length > 20) {     return (       <div className="alert alert-danger" part="alert">         The username must be between 3 and xx characters.       </div>     );   } }; const vpassword = (value) => {   if (value.length < 6 || value.length > 40) {     return (       <div className="alert alert-danger" office="alert">         The password must be between half dozen and xl characters.       </div>     );   } }; const Annals = () => {   const form = useRef();   const checkBtn = useRef();   const [username, setUsername] = useState("");   const [email, setEmail] = useState("");   const [password, setPassword] = useState("");   const [successful, setSuccessful] = useState(imitation);   const { message } = useSelector(land => state.message);   const dispatch = useDispatch();   const onChangeUsername = (e) => {     const username = e.target.value;     setUsername(username);   };   const onChangeEmail = (e) => {     const e-mail = e.target.value;     setEmail(email);   };   const onChangePassword = (due east) => {     const password = due east.target.value;     setPassword(password);   };   const handleRegister = (e) => {     due east.preventDefault();     setSuccessful(imitation);     form.electric current.validateAll();     if (checkBtn.electric current.context._errors.length === 0) {       dispatch(register(username, e-mail, countersign))         .and so(() => {           setSuccessful(true);         })         .take hold of(() => {           setSuccessful(fake);         });     }   };   return (     <div className="col-doc-12">       <div className="menu card-container">         <img           src="//ssl.gstatic.com/accounts/ui/avatar_2x.png"           alt="profile-img"           className="profile-img-card"         />         <Form onSubmit={handleRegister} ref={form}>           {!successful && (             <div>               <div className="form-grouping">                 <characterization htmlFor="username">Username</label>                 <Input                   type="text"                   className="form-command"                   name="username"                   value={username}                   onChange={onChangeUsername}                   validations={[required, vusername]}                 />               </div>               <div className="class-group">                 <label htmlFor="e-mail">Email</label>                 <Input                   type="text"                   className="class-command"                   proper noun="email"                   value={email}                   onChange={onChangeEmail}                   validations={[required, validEmail]}                 />               </div>               <div className="form-group">                 <characterization htmlFor="countersign">Countersign</characterization>                 <Input                   type="password"                   className="course-control"                   name="password"                   value={password}                   onChange={onChangePassword}                   validations={[required, vpassword]}                 />               </div>               <div className="course-group">                 <push button className="btn btn-chief btn-block">Sign Upwardly</push>               </div>             </div>           )}           {bulletin && (             <div className="form-group">               <div className={ successful ? "warning warning-success" : "warning alert-danger" } part="alarm">                 {message}               </div>             </div>           )}           <CheckButton style={{ brandish: "none" }} ref={checkBtn} />         </Form>       </div>     </div>   ); }; export default Register;                  

Profile Page

This page gets electric current User from Local Storage past getting user in the application state and show user information (with token).

components/Profile.js

          import React from "react"; import { Redirect } from 'react-router-dom'; import { useSelector } from "react-redux"; const Profile = () => {   const { user: currentUser } = useSelector((state) => land.auth);   if (!currentUser) {     render <Redirect to="/login" />;   }   return (     <div className="container">       <header className="jumbotron">         <h3>           <strong>{currentUser.username}</strong> Profile         </h3>       </header>       <p>         <stiff>Token:</potent> {currentUser.accessToken.substring(0, twenty)} ...{" "}         {currentUser.accessToken.substr(currentUser.accessToken.length - twenty)}       </p>       <p>         <potent>Id:</strong> {currentUser.id}       </p>       <p>         <strong>Email:</stiff> {currentUser.e-mail}       </p>       <strong>Regime:</strong>       <ul>         {currentUser.roles &&           currentUser.roles.map((part, alphabetize) => <li key={alphabetize}>{role}</li>)}       </ul>     </div>   ); }; export default Contour;                  

Create React Pages for accessing Resources

These pages will use UserService to asking data from API.


components

Home.js

BoardUser.js

BoardModerator.js

BoardAdmin.js


Domicile Folio

This is a public page that shows public content. People don't demand to log in to view this page.

components/Abode.js

          import React, { useState, useEffect } from "react"; import UserService from "../services/user.service"; const Home = () => {   const [content, setContent] = useState("");   useEffect(() => {     UserService.getPublicContent().then(       (response) => {         setContent(response.data);       },       (error) => {         const _content =           (fault.response && error.response.information) ||           mistake.message ||           error.toString();         setContent(_content);       }     );   }, []);   return (     <div className="container">       <header className="jumbotron">         <h3>{content}</h3>       </header>     </div>   ); }; consign default Abode;                  

Role-based Pages

We're gonna have three pages for accessing protected data:

  • BoardUser page calls UserService.getUserBoard()
  • BoardModerator folio calls UserService.getModeratorBoard()
  • BoardAdmin page calls UserService.getAdminBoard()

I will show you User Page for example, other Pages are similar to this Page.

components/BoardUser.js

          import React, { useState, useEffect } from "react"; import UserService from "../services/user.service"; const BoardUser = () => {   const [content, setContent] = useState("");   useEffect(() => {     UserService.getUserBoard().then(       (response) => {         setContent(response.data);       },       (error) => {         const _content =           (error.response &&             fault.response.information &&             error.response.data.message) ||           error.message ||           error.toString();         setContent(_content);       }     );   }, []);   return (     <div className="container">       <header className="jumbotron">         <h3>{content}</h3>       </header>     </div>   ); }; export default BoardUser;                  

Add Navbar and define Routes

Create React Router History

This is a custom history object used by the React Router.

helpers/history.js

          import { createBrowserHistory } from "history"; export const history = createBrowserHistory();                  

Modify App Page

Now we add a navigation bar in App Page. This is the root container for our awarding.
The navbar dynamically changes by login status and electric current User'southward roles.

  • Dwelling: always
  • Login & Sign Up: if user hasn't signed in yet
  • User: in that location is user value in the application state
  • Lath Moderator: roles includes ROLE_MODERATOR
  • Board Admin: roles includes ROLE_ADMIN

src/App.js

          import React, { useState, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { Router, Switch, Road, Link } from "react-router-dom"; import "bootstrap/dist/css/bootstrap.min.css"; import "./App.css"; import Login from "./components/Login"; import Annals from "./components/Annals"; import Home from "./components/Home"; import Profile from "./components/Profile"; import BoardUser from "./components/BoardUser"; import BoardModerator from "./components/BoardModerator"; import BoardAdmin from "./components/BoardAdmin"; import { logout } from "./actions/auth"; import { clearMessage } from "./actions/message"; import { history } from "./helpers/history"; const App = () => {   const [showModeratorBoard, setShowModeratorBoard] = useState(false);   const [showAdminBoard, setShowAdminBoard] = useState(false);   const { user: currentUser } = useSelector((state) => country.auth);   const dispatch = useDispatch();   useEffect(() => {     history.mind((location) => {       dispatch(clearMessage()); // clear message when changing location     });   }, [acceleration]);   useEffect(() => {     if (currentUser) {       setShowModeratorBoard(currentUser.roles.includes("ROLE_MODERATOR"));       setShowAdminBoard(currentUser.roles.includes("ROLE_ADMIN"));     }   }, [currentUser]);   const logOut = () => {     dispatch(logout());   };   render (     <Router history={history}>       <div>         <nav className="navbar navbar-aggrandize navbar-night bg-nighttime">           <Link to={"/"} className="navbar-brand">             bezKoder           </Link>           <div className="navbar-nav mr-auto">             <li className="nav-particular">               <Link to={"/abode"} className="nav-link">                 Home               </Link>             </li>             {showModeratorBoard && (               <li className="nav-item">                 <Link to={"/mod"} className="nav-link">                   Moderator Board                 </Link>               </li>             )}             {showAdminBoard && (               <li className="nav-item">                 <Link to={"/admin"} className="nav-link">                   Admin Board                 </Link>               </li>             )}             {currentUser && (               <li className="nav-item">                 <Link to={"/user"} className="nav-link">                   User                 </Link>               </li>             )}           </div>           {currentUser ? (             <div className="navbar-nav ml-motorcar">               <li className="nav-particular">                 <Link to={"/profile"} className="nav-link">                   {currentUser.username}                 </Link>               </li>               <li className="nav-item">                 <a href="/login" className="nav-link" onClick={logOut}>                   LogOut                 </a>               </li>             </div>           ) : (             <div className="navbar-nav ml-auto">               <li className="nav-item">                 <Link to={"/login"} className="nav-link">                   Login                 </Link>               </li>               <li className="nav-particular">                 <Link to={"/register"} className="nav-link">                   Sign Up                 </Link>               </li>             </div>           )}         </nav>         <div className="container mt-iii">           <Switch>             <Route exact path={["/", "/home"]} component={Home} />             <Route exact path="/login" component={Login} />             <Road exact path="/register" component={Register} />             <Route exact path="/profile" component={Contour} />             <Route path="/user" component={BoardUser} />             <Route path="/modern" component={BoardModerator} />             <Route path="/admin" component={BoardAdmin} />           </Switch>         </div>       </div>     </Router>   ); }; export default App;                  

You can simplify import statement with:
Absolute Import in React

Logout when Token is expired

There are two ways to handle JWT Token expiration.
For more details, please visit:
Handle JWT Token expiration in React with Hooks

Add CSS style for React Pages

Open src/App.css and write some CSS code as post-obit:

          label {   display: cake;   margin-top: 10px; } .card-container.card {   max-width: 350px !important;   padding: 40px 40px; } .carte {   background-color: #f7f7f7;   padding: 20px 25px 30px;   margin: 0 auto 25px;   margin-top: 50px;   -moz-edge-radius: 2px;   -webkit-border-radius: 2px;   border-radius: 2px;   -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.iii);   -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.iii);   box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); } .profile-img-card {   width: 96px;   superlative: 96px;   margin: 0 motorcar 10px;   display: block;   -moz-border-radius: 50%;   -webkit-border-radius: 50%;   border-radius: 50%; }                  

Configure Port for React JWT Auth Customer with Web API

Considering most of HTTP Server utilise CORS configuration that accepts resource sharing restricted to some sites or ports, so we also need to configure port for our App.

In project folder, create .env file with following content:

          PORT=8081                  

Now nosotros've set our app running at port 8081. Y'all will need to do this work if you utilise one of post-obit Servers:

  • Spring Boot JWT Authentication with Jump Security, MySQL
  • Jump Boot JWT Hallmark with Spring Security, PostgreSQL
  • Spring Kick JWT Hallmark with Jump Security, MongoDB
  • Node.js JWT Authentication & Authorization with MySQL
  • Node.js JWT Authentication & Authorization with PostgreSQL
  • Node.js JWT Authentication & Authorization with MongoDB

Conclusion

Congratulation!

Today we've done so many interesting things. I hope you understand the overall layers of our React Redux Registration & Login App using Hooks, LocalStorage, React Router, Thunk Middleware, Axios, Bootstrap. Now y'all can apply it in your projection at ease.

Don't forget to read this tutorial:
Handle JWT Token expiration in React with Hooks

If you don't desire to use React Redux for this example, you tin discover the implementation at:
– React Hooks: JWT Hallmark (without Redux) example
– React Components: JWT Authentication (without Redux) instance

If y'all need Form Validation with React Hook Form seven, delight visit:
React Form Validation with Hooks example

Or use React Components:
React Redux: Token Authentication example with JWT & Axios

Or add refresh token:
React + Redux: Refresh Token with Axios and JWT example

Happy learning, see you again!

Farther Reading

  • React Router Guide
  • React Hooks
  • Redux Tutorials
  • https://world wide web.npmjs.com/bundle/react-validation
  • https://world wide web.npmjs.com/package/validator
  • In-depth Introduction to JWT-JSON Web Token

Fullstack Crud:
– React + Bound Boot + MySQL
– React + Spring Boot + PostgreSQL
– React + Spring Boot + MongoDB
– React + Node.js Express + MySQL
– React + Node.js Limited + PostgreSQL
– React + Node.js Limited + MongoDB
– React + Django

Serverless:
– React Hooks + Firebase Realtime Database: CRUD App
– React Hooks + Firestore instance: Crud app

Source Code

You can discover the complete source code for this tutorial on Github.

Using redux-toolkit: React Redux Login, Annals case with redux-toolkit & Hooks

React When Login Change the Navigation Bar State

DOWNLOAD HERE

Source: https://www.bezkoder.com/react-hooks-redux-login-registration-example/

Posted by: yoostol1955.blogspot.com

Comments