Authentication Features in React are primary and widely use features and can be performed in different ways. In React Library we can easily create a function that can authenticate and render components accordingly. In short, we are gonna save and use the data of logged-in users throughout the different pages of the web application.
Note: – React is a front-end library we will be using any random API to authenticate in the backend and then store the data in states to validate the authentication and use it to render components.
Packages: –
- React
- react-router-dom
Create the Reducer
Reducer is the function the will hook the data to the state and can send data to different pages which are rendered under its Provider. This file is created in the src>reducers folder as per the standard conventions, moreover, reducers can be work with different properties other than authentication. But here we will use it for authentication.
export const initialState = null; export const reducer = (state,action) =>{ if(action.type === "USER"){ return action.payload } if(action.type === "CLEAR"){ return null } return state }
we have to use the initialState as null as at the start no one will be logged in. Exporting the function with parameters state and action. State Define the current state and action perform different tasks and returns the payload. Payload is the data that is stored in states and used all over the Web App.
App.js file configuration
import React, { createContext,useContext,useReducer,useEffect } from 'react'; import {BrowserRouter as Router,Route,Switch} from 'react-router-dom'; import {reducer,initialState} from './reducer/userReducer'; export const UserContext = createContext(); const Routing = () => { const {state,dispatch} = useContext(UserContext); useEffect(()=>{ const user = JSON.parse(localStorage.getItem("user")) if(user){ dispatch({type:"USER",payload:user}) } },[]) return( <Switch> <Route exact path="/"><Home /></Route> <Route exact path="/login"><Login /></Route> </Switch> ) } function App() { const [state,dispatch] = useReducer(reducer,initialState) return ( <UserContext.Provider value={{state,dispatch}} > <Router> <Navbar /> <Routing /> <Footer /> </Router> </UserContext.Provider> ); } export default App;
Here we imported the reducer and using the useEffect hook as each time page reload we get the status that is there any user is logged in. And in the App function, we render the pages under the Provider of the given reducer which helps in saving the data to states.
Login Function
In Login, the function collects the inputs using the form and stores them in variables, and then passes them with the specific API or URL. After calling the URL then the returned data we use the dispatch function of the useContext Hook to save the data in states and give access rights to the authenticated user.
import React,{useState,useContext} from 'react'; import {Link,useHistory} from 'react-router-dom' import axios from 'axios' import { UserContext } from '../App'; const Login = () => { const {state,dispatch} = useContext(UserContext) const history = useHistory() const [values,setValues] = useState({ userName:'', password: '', }) const {userName,password} = values; const handleChange = name => e => { setValues({...values,[name]:e.target.value}) }; const handleSubmit = (e) => { localStorage.removeItem('user') e.preventDefault(); setValues({...values,error:false}) if(!userName || !password){ console.log('missing') // M.toast({html:"Empty Fields",classes:"#c62828 red darken-3"}) return } axios(`http://localhost:8084/api/hm/user/search/getAuthentication?userName=${userName}&password=${password}`) .then(data=>{ console.log(data) localStorage.setItem("user",JSON.stringify(data.data)) dispatch({type:"USER",payload:data.data}) // M.toast({html:"Signedin Success",classes:"#43a047 green darken-1"}) history.push('/landing') }).catch((err) =>{ setValues({...values,error:true}); // M.toast({html:"Invalid Credentials",classes:"#c62828 red darken-3"}) console.log(err) } ) } return ( <> <br /> <nav aria-label="breadcrumb"> <ol className="breadcrumb" style={{padding:'13px','backgroundColor': '#074235'}}> <li className="breadcrumb-item text-light"><Link to="/">Home</Link></li> <li className="breadcrumb-item text-light active" aria-current="page">Login</li> </ol> </nav> <hr /> <div className="container"> <div className="card shadow mb-5 bg-body rounded" style={{ width: '700px' }}> <h5 className="card-header" style={{ 'backgroundColor': '#074235', color: 'white' }}>Login</h5> <div className="card-body"> <form type="post" className="form-floating"> <div className="mb-3"> <label htmlFor="exampleInputEmail1" className="form-label">UserName </label> <input required placeholder="Enter username" onChange={handleChange('userName')} className="form-control" /> <div className="form-text"><font color="red" style={{ 'fontSize': '13px' }}></font></div> </div> <div className="mb-3"> <label htmlFor="exampleInputPassword1" className="form-label">Password</label> <input required type="password" placeholder="Enter Password" onChange={handleChange('password')} className="form-control" /> <div className="form-text"><font color="red" style={{ 'fontSize': '13px' }}></font></div> </div> <button type="submit" className="btn btn-primary pull-right" onClick={e => handleSubmit(e)} >Login</button> </form> </div> </div> </div> </> ) } export default Login
Use the Console of the Browser to check on the state of the web app or see the localStorage under the Application section in chrome developer tools