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?
2
Answers
You need a
loading
state or equivalent (e.g.loggedIn
state initialized asnull
, and interpreting thisnull
value as "loading").Then do not render your
<PrivateRoute>
component while you are still loading:Or handle the loading state within
<PrivateRoute>
to prevent redirecting before loaded:First make sure that
loggedIn
state is changing.You can use this code snippet I used for this exact matter.
I’m using React Router +6 here.