Daniel Kormos
Daniel Kormos

Reputation: 280

Setting state in react useEffect not happening before gets to the route

app.js


    const [isLoggedIn, setIsLoggedIn] = useState(false);

    useEffect(() => {
        
        fetch('http://localhost:5000/usersystem/user/isloggedin', {
            method: 'GET',
            credentials: 'include',
            mode: 'cors'
        }).then(response => response.json())
        .then(response => {
            setIsLoggedIn(response.success);
        })

    }, []);

    return (
        <div className="App">
            <AppContext.Provider value={{ isLoggedIn, setIsLoggedIn }}>
                <Routes />
            </AppContext.Provider>
        </div>
    );
}

routes.js

export default function Routes() {
    return (
        <Switch>
            <ProtectedRoute exact path="/">
                <Dashboard />
            </ProtectedRoute>
            <Route exact path="/login">
                <Login />
            </Route>
            <Route>
                <Notfound />
            </Route>
        </Switch>
    );
}

protectedroute.jsx

import React from "react";
import { Route, Redirect, useLocation } from "react-router-dom";
import { useAppContext } from "../libs/ContextLib";

export default function ProtectedRoute({ children, ...rest }) {
  const { pathname, search } = useLocation();
  const { isLoggedIn } = useAppContext();
    
  return (
    <Route {...rest}>
      {isLoggedIn ? (
        children
      ) : (
        <Redirect to={
          `/login?redirect=${pathname}${search}`
        } />
      )}
    </Route>
  );
}

I have a node express app on port 5000, which handles user authentication with passport and cookie session. It works all good, the session cookies gets to the browser, and can read it and can send it back to authenticate the user.

However, in react, when i refresh the browser the user gets redirected to the login page instead of the dashboard, even with the session cookies in the browser.

It feels like the setIsLoggedIn(response.success) in app.js, wont update isLoggedIn before it gets to the ProtectedRoute and redirects to login.

Im into this for 4 hours now, and couldnt solve it. Can someone please suggest me a way to do this, or tell me what is the problem, so when i refresh the page it wont redirect to login? Thanks.

Upvotes: 1

Views: 157

Answers (1)

michmich112
michmich112

Reputation: 774

Your component is rendered once when you create the component. Your setIsLoggedIn will update the state and re-render it. You could put in a Loader to wait for the data to come before displaying the page you want. E.g:

function MyComponent () {
   const [isLoggedIn, setIsLoggedIn] = useState(null);

    useEffect(() => {
        
        fetch('http://localhost:5000/usersystem/user/isloggedin', {
            method: 'GET',
            credentials: 'include',
            mode: 'cors'
        }).then(response => response.json())
        .then((response, err) => {
            if(err) setIsLoggedIn(false); // if login failure
            setIsLoggedIn(response.success);
        })
        

    }, []);

    if(isLoggedIn === null) return (<div>Loading</div>);

    // this is only rendered once isLoggedIn is not null
    return (
        <div className="App">
            <AppContext.Provider value={{ isLoggedIn, setIsLoggedIn }}>
                <Routes />
            </AppContext.Provider>
        </div>
    );
}

Upvotes: 1

Related Questions