skip to Main Content

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


  1. 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" />
      );
    };
    
    Login or Signup to reply.
  2. First make sure that loggedIn state is changing.

    • your problem might be because of state changing and if you use a function to validate if the user is loggedIn or not. would be better.

    You can use this code snippet I used for this exact matter.
    I’m using React Router +6 here.

     <BrowserRouter>
          <Routes>
            <Route path="auth/*" element={<AuthPages />} />
    
    
            <Route path="/" element={<Navigate to="/admin/dashboard" />} />
            <Route
              path="admin/*"
              element={
                isAuthenticated() ? (
                  <AdminRoutes />
                ) : (
                  <Navigate to={'/auth/login'} />
                )
              }
            />
            <Route path="auth/login/verify" element={<TwoFactorPage />} />
          </Routes>
        </BrowserRouter>
    

    isAuthenticated is a simple function that checks if the user state has filled with data, and if so it will return true.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search