ReactJS: Protected Routes Implementation in ReactJS


Protected Routes are routes that can only be accessed if a condition is met(usually, if user is properly authenticated). It returns a Route that either renders a component or redirects a user to another route based on a set condition. We will use this method if we want to separate between specific user and public user in accessing pages in our website by using ReactJS platform.

Step-by-step example to use this protected routes method
I have created some pages as a sample in implementing Protected Routes which can be accessed from URL below.


From many files in that link, some pages which are related to Protected Routes method are explained below.

1. Codes for App.js file in src folder

import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import 'bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import Navbar from './components/navbar';
import Home from './pages/AboutMe';
import ReactExample from './pages/ReactExample';
import Hooks1 from './pages/Hooks1';
import Hooks2 from './pages/Hooks2';
import Hooks3 from './pages/Hooks3';
import Hooks4 from './pages/Hooks4';
import Book from './pages/Book';
import Contributor from './pages/Contributor';
import Login from './pages/LoginPage';
import Register from './pages/Register';
import EmailFeedback from './pages/EmailFeedback';
import ProtectedRoute from './components/ProtectedRoute';
import { NotificationContainer } from 'react-notifications';
import 'react-notifications/lib/notifications.css';


function App() {

return (

<BrowserRouter>
<Helmet>
<title>Learning React</title>
</Helmet>
<Navbar />
<Switch>
<Route exact path="/" component={Home} />
<ProtectedRoute path="/ReactExample" component={ReactExample} />
<Route path="/Hooks1" component={Hooks1} />
<Route path="/Hooks2" component={Hooks2} />
<Route path="/Hooks3" component={Hooks3} />
<Route path="/Hooks4" component={Hooks4} />
<Route path="/Book" component={Book} />
<ProtectedRoute path="/Contributor" component={Contributor} />
<Route path="/EmailFeedback" component={EmailFeedback} />
<Route path="/LoginPage" component={Login} />
<Route path="/Register" component={Register} />
</Switch>
<NotificationContainer />
</BrowserRouter>
);
}

export default App;


2. Codes for ProtectedRoute.js file in components folder

import React from 'react';
import { Redirect, Route } from 'react-router-dom';
import { connect } from 'react-redux';
import { NotificationManager} from 'react-notifications';

const ProtectedRoute = ({ isAuth, component: Component, ...rest }) => {
return (
<Route
{...rest}
render={routeProps => {
if(isAuth) {
return <Component {...routeProps} />
} else {
NotificationManager.error('You are not logged in yet','',1000);
return (
<Redirect to="/" />
)
}
}}
/>
);
};

const mapStateToProps = (state) => ({
isAuth: state.auth.isAuthenticated
});

export default connect (mapStateToProps)(ProtectedRoute);


3. Codes for reducer.js file in redux/authentication folder

import { LOG_IN, LOG_OUT } from './actionTypes';
import { NotificationManager} from 'react-notifications';

const initialState = {
// isAuthenticated: false,
isAuthenticated: localStorage.getItem("keepLogin"),// Activate login after page refresh
};

const authReducer = (state = initialState, action) => {
if (action.type === LOG_IN) {
NotificationManager.success('You are logged in','',1000);
return {
...state,
isAuthenticated: true,
}
} else if (action.type === LOG_OUT) {
NotificationManager.warning('You have logged out successfully','',1000);
return {
...state,
isAuthenticated: false,
}
}
return state;
};

export default authReducer;


4. Codes for action.js file in redux/authentication folder

import { LOG_IN, LOG_OUT } from './actionTypes';

export const logInAction = {
type: LOG_IN,
};

export const logOutAction = {
type: LOG_OUT,
};


5. Codes for actionTypes.js file in redux/authentication folder

export const LOG_IN = 'LOG_IN';
export const LOG_OUT = 'LOG_OUT';


6. Codes for LoginPage.js file in pages folder

import React, { useState } from 'react';
import { Card } from 'react-bootstrap';
import { connect } from 'react-redux';
import { logInAction, logOutAction } from '../redux/authentication/actions';
import { useHistory } from 'react-router-dom';
import qs from 'qs';
import axios from 'axios';

const Login = (props) => {

// -------
const [signInData, setSignInData] = useState({
email: '',
password: ''
});

const handleChangeSignIn = (e) => {
setSignInData({
...signInData,
[e.target.name] : e.target.value
})
}
// -------

// -------
const [data, setData] = useState({});

const handleSubmitSignIn = (e) => {
e.preventDefault();
axios({
method: 'post',
url: 'https://reqres.in/api/register',
data: qs.stringify({
email: signInData.email,
password: signInData.password,
}),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
}).then((response) => {
console.log('response =>', response.data.token);
setData(response.data.token);

if (data.token !== null) {
localStorage.setItem('keepLogin', JSON.stringify (response.data.token)); // Keep login while page refresh
handleClick();
} else {
console.log('response error', response.data.token);
}
});
}

const { isLogin, logInFunc, logOutFunc } = props;
const history = useHistory();
// console.log('props login page =>', props);

const handleClick = () => {
if (isLogin) {
logOutFunc();
history.push('/');
} else {
logInFunc();
history.push('/ReactExample');
}
}

// -------
// -------
const handleSignOut = () => {
logOutFunc();
history.push('/');
localStorage.clear();
}
// -------


return (
<center>
<Card style={{ width: '22rem' }}>
<Card.Body>
<form>
<div className="App">
<span style={{color: 'black'}}>{isLogin ? 'You are logged in' : null}</span>
<h1 style={{backgroundColor: '#D4EFDF'}}>{isLogin ? null : 'Login'}</h1>
</div>

<div className="form-group" style={{textAlign: 'left'}}>
<label>{isLogin ? null : 'Email address'}</label>
<input
type={isLogin ? 'hidden' : 'email'}
name="email" // Auth Key
className="form-control"
placeholder="eve.holt@reqres.in"
onChange={handleChangeSignIn}
/>
</div>

<div className="form-group" style={{textAlign: 'left'}}>
<label>{isLogin ? null : 'Password'}</label>
<input
type={isLogin ? 'hidden' : 'password'}
name="password" // Auth Key
className="form-control"
placeholder="pistol"
onChange={handleChangeSignIn}
/>
</div>

{/* email: eve.holt@reqres.in */}
{/* password: pistol */}

<button
onClick={isLogin ? handleSignOut : handleSubmitSignIn}
type="submit"
className="btn btn-primary btn-block">
{isLogin ? 'Logout' : 'Login'}
</button>

<p className="forgot-password text-right">
<a href="/">{isLogin ? null : 'Forgot password?'}</a>
</p>

</form>
</Card.Body>
</Card>
</center>
);
};

const mapStateToProps = (state) => ({
isLogin: state.auth.isAuthenticated
});

const mapDispatchToProps = (dispatch) => ({
logInFunc: () => dispatch(logInAction),
logOutFunc: () => dispatch(logOutAction)
});

export default connect(mapStateToProps, mapDispatchToProps)(Login);


From all of codes above the pages will be displayed like this link:

Easy enough to be implemented and enhanced. Hopefully this article help you to configure Protected Routes in your ReactJS website.

Comments

Popular posts from this blog

How to Inspect Problems in Your ReactJS Codes

ReactJS Hooks: How to Use useState in ReactJS?