Reputation: 41
I'm trying to change the root of my app to render a different Router if the user authenticates. (public marketing website then the SAAS app when logged in).
My current code:
class MainRouter extends React.Component {
render() {
if(isAuthenticated()) {
return <AppRouter/>
} else {
return <FrontRouter/>
}
}
}
This works but I have to refresh the browser after authenticating or logging out otherwise it throws errors trying to render components that require a user.
isAuthenticated:
export const isAuthenticated = () => {
if(typeof window == 'undefined') {
return false
}
if(localStorage.getItem('jwt')) {
return JSON.parse(localStorage.getItem('jwt'))
} else {
return false;
}
};
Upvotes: 0
Views: 1052
Reputation: 38
Consider using state (ideally with hooks, or Redux if you are comfortable) to hold the JWT in memory. The idea is to store it immediately after logging in and have it available to use through component (or Redux) state. Then upon refreshing the page, state will still load from localState or cookies.
A secondary point, LocalStorage can act differently across different browsers, and even more so with privacy settings. Consider using cookies rather than localStorage as its usage is more predictable and consistent, plus the security risk is more or less the same. (code example below)
Third, I highly recommend switching from class-based components to function-based components to take advantage of React's new Hooks API. It is a much simpler way to manage state and saves you many lines of code.
// library imports
import React from 'react';
// component imports
import AppRouter from './AppRouter';
import FrontRouter from './FrontRouter';
// main
export default function MainRouter({isAuthenticated}) {
return isAuthenticated ? <AppRouter/> : <FrontRouter/>
}
If "isAuthenticated" is a boolean variable created by React's "useState" function from parent component, you can pass that variable to "MainRouter" component and conditionally render "AppRouter" or "FrontRouter" (I'm using a ternary operator instead of an "If/Else" statement to save lines)
In this case, the parent component file would look like this:
// in ParentComponent.jsx
// library imports
import React, {useState} from 'react';
// component imports
import MainRouter from './MainRouter';
// main component
export default function ParentComponent() {
// set state here
const defaultState = false;
const [isAuthenticated, setIsAuthenticated] =useState(defaultState);
return (
<div className="ParentComponent" >
<MainRouter isAuthenticated={isAuthenticated} />
</div>
)
}
helper function for getting cookies from w3schools (https://www.w3schools.com/js/js_cookies.asp)
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
Upvotes: 1