I've came across a problem with protected routes and the authentication of protected routes.
I'm using an AuthContext for the whole user authentication across the webapp. I save all the user-data inside a state. With the help of useEffect and the sessionStorage I store the user object so It can be used after a page reload.
[...]
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState({})
useEffect(() => {
const sessionUser = sessionStorage.getItem("user")
if(!sessionUser) return
changeUser(JSON.parse(sessionUser))
}, [])
const hasRank = (ranks) => {
if(!Object.keys(user).length > 0) return false
const matchingPerms = ranks.filter(rank => user.rank.includes(rank))
return matchingPerms.length > 0
}
const changeUser = (data) => {
setUser(data)
if(Object.keys(data).length > 0) {
return sessionStorage.setItem("user", JSON.stringify(data))
}
return sessionStorage.removeItem("user")
}
}
[...]
In order to protect certain pages I'm using a Protected Route Component that checks whether the user is logged in or not.
[...]
const auth = useContext(AuthContext)
const isAuthorized = auth.hasRank(rest.rank)
<Route
{...rest}
render={props => {
return isAuthorized ? (
<Component {...props} />
) : (
<Redirect to="/auth/login" />
)
}}
/>
The saving and fetching into and from the sessionStorage works fine until I want to render content that's inside a protected route - I always get redirected to the login page, because the user object is empty because of the reload and the state is not being updated early enough. Therefore the protected route checks for authentication with an empty object, which results in a redirect to the login page.
How can I wait until the user state is being updated before checking the authentication inside the protected route?
EDIT:
App Component:
return (
<Router>
<Switch>
<Route path="/auth/register" component={Register} />
<Route path="/auth/login" component={LogIn} />
<Route path="/err/404" component={Page404} />
<Route path="/" component={PanelRoutes}/>
</Switch>
</Router>
)
PanelRoutes Component:
return (
<div className="skin-default fixed-layout">
<div id="main-wrapper">
<Topbar />
<Sidebar />
<div className="page-wrapper">
<div className="container-fluid">
<Switch>
<Route exact path="/" component={Homepage} />
<Route exact path="/legal/imprint" component={Imprint} />
<Route exact path="/legal/privacy" component={Privacy} />
<ProtectedRoute exact path="/mc/sounds" component={McSounds} rank={["ADMIN", "MC"]} />
<ProtectedRoute exact path="/admin/users" component={AdminUsers} rank={["ADMIN"]} />
</Switch>
</div>
</div>
</div>
</div>
)
Kind Regards