I have a single-page React application with a very basic setup (compressed here):
function App() {
const [ userLogin, setUserLogin ] = useState(null);
useEffect(() => {
try {
const result = AuthService.getAuthenticatedUser();
setUserLogin(result);
} catch (error) {
console.error('Error fetching login data: ', error);
}
}, []);
function RequireAuthentication({ redirectTo }) {
return userLogin ? <Outlet /> : <Navigate to={redirectTo} />;
}
return (
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route path="/login" element={ <LoginPage /> } />
<Route path="/logout" element={ <LogoutPage /> } />
<Route path="/" element={ <RequireAuthentication redirectTo="/login" /> }>
<Route path="/" element={ <div>lol</div> } />
<Route path="option1" element={ <div>option1</div> } />
<Route path="option2" element={ <div>option2</div> } />
<Route path="option3" element={ <div>option</div> } />
</Route>
<Route path="*" element={ <Navigate to="/" /> } />
</Routes>
</BrowserRouter>
</React.StrictMode>
);
}
Right now my AuthService just looks at local storage and I will expand that to something that makes a REST API call to verify the persisted token is actually valid (and that the API is generally available).
I have two questions here, one of which I have a workaround answer to:
- What is the idiomatic way to add a header/navbar that is hidden on the login page? (workaround below, and this is just for bonus points)
- The primary question: My implementation currently resides in
useEffect, which throws off theRequireAuthenticationfunction. How do I force that to be evaluated and run the redirect only after theuseEffectfunction completed?
I tried to put the call to AuthService.getAuthenticatedUser in the RequiredAuthentication function, but I am having problems making inline calls to Rest APIs and the solution I was pointed to was to use useEffect with async and await.
For my workaround on hiding a header, my workaround is something like this, where I render it as a parent above the BrowserRouter element:
return (
<div className={ useLoggedIn ? 'hidden' : undefined }>This is my nav bar.</div>
);
Other things I looked at: