my App declaration looks like this
function App() {
const [loggedIn, setLoggedIn] = useState(false);
const [username, setUsername] = useState('')
const [userId, setUserId] = useState(0)
const [error, setError] = useState('')
useEffect(() => {
fetchSessionData(setLoggedIn, setUsername, setUserId, setError)
}, [])
fetchSessionData calls the server and receives information about username and userId and sets the variables. Next i have routing
<Switch>
<Route exact path="/games/new">
<PrivateRoute isLogged={loggedIn}>
<MyComponent />
</PrivateRoute>
</Route>
<Switch/>
With PrivateRoute looking like this:
const PrivateRoute = ({ children, isLogged }: { children: JSX.Element, isLogged: boolean }): JSX.Element => {
return (
isLogged ? children : <Redirect to="/sign_in" />
);
};
Its a simple system meant to assure that certain routes will only be accessible if the user is signed in. HOWEVER. Even if im actually signed in, the isLogged var seems to always be false.
I believe its because the routing part gets rendered before the answer from the server actually gets received and variables set.
Question is very simple, how to modify this architecture so the loggedIn variable is read after the response from the server?
>Solution :
You need a loading state or equivalent (e.g. loggedIn state initialized as null, and interpreting this null value as "loading").
Then do not render your <PrivateRoute> component while you are still loading:
{
loggedIn !== null && <PrivateRoute isLogged={loggedIn}>
<MyComponent />
</PrivateRoute>
}
Or handle the loading state within <PrivateRoute> to prevent redirecting before loaded:
const PrivateRoute = ({
children,
isLogged
}: {
children: JSX.Element,
isLogged: boolean | null
}): JSX.Element => {
return (
isLogged === null
? "Checking user account..."
: isLogged
? children
: <Redirect to="/sign_in" />
);
};