axern
axern

Reputation: 47

Losing Context upon page refresh

I have following problem - my Context works good, until I refresh my page. For example if I'm on ProtectedRoute and try to refresh, my "loggedIn" property sets for a moment to false and redirects me to home page.

Context:

export const Context = createContext();

export const ContextProvider = (props) => {
    const [loggedIn, setLoggedIn] = useState(false);
    const [userRole, setUserRole] = useState('');
    useEffect(() => {
        if (localStorage.getItem("loggedIn") === "true") {
            setLoggedIn(true);
        }
        else {
            setLoggedIn(false);
        }
    }, [])

    return (
        <Context.Provider
            value={[loggedIn, userRole, setLoggedIn]}>
            {props.children}
        </Context.Provider>
    );
}

ProtectedRoute:

const ProtectedRoute = ({ component: Component, ...rest }) => {
    const [loggedIn] = useContext(Context);


    return (
        <Route
            {...rest}
            render={(props) =>
                loggedIn ? <Component {...props} /> : <Redirect to='/login' />
            }
        />
    );
};
export default ProtectedRoute;

index.js:


ReactDOM.render(
  <ContextProvider>
    <App />
  </ContextProvider>,
  document.getElementById('root')
);
reportWebVitals();

App.js:

export default function App() {
  const [loggedIn] = useContext(Context);
  console.log(loggedIn)
  return (
      <div className="background">
        <Router>
          <Navigation />
          <Scores />
          <div className="content">
            <Route exact path="/" component={Home} />
            <Route path="/login" component={Login} />
            <Route path="/register" component={Register} />
            <ProtectedRoute path="/players/:id" exact={true} component={PlayerStats} />
            <ProtectedRoute path="/players" component={PlayerList} />
            <ProtectedRoute path="/team/:id" exact={true} component={MyTeamDetails} />
            <ProtectedRoute path="/myteams" exact={true} component={MyTeamList} />
            <ProtectedRoute path='/logout' />
          </div>
        </Router>
      </div>
  );
}

And that's my function to handle login:

export const Login = () => {
    const [loggedIn, userRole, setLoggedIn] = useContext(Context);
    const [password, setPassword] = useState("")
    const [showPassword, setShowPassword] = useState(false);
    const [username, setUsername] = useState("");

    const updateUsername = (e) => {
        setUsername(e.target.value)
    }

    const updatePassword = (e) => {
        setPassword(e.target.value)
    }

    function handleSubmit(e) {
        e.preventDefault();
        axios({
            method: 'post',
            url: 'https://localhost:44324/authentication/login',
            data: {
                "login": username,
                "password": password
            },
            
        }).then((res) => {
            if (res.data.result == "SUCCESS") {
                localStorage.setItem('loggedIn', 'true');
                setLoggedIn(true);
            } else {
                console.log(res.data);
            }
        }).catch((error) => {
            console.log(error);
        });
    }

To specify - if I refresh page when I'm on "/myteams", it redirect me to "/". I tried to check my loggedIn state and it seems like it's dissappears for really short time upon refresh, then comes back to normal.

Upvotes: 2

Views: 303

Answers (1)

dave
dave

Reputation: 64657

setState (and it's hooks variant) runs asynchronously, so when you do:

const [loggedIn, setLoggedIn] = useState(false);
useEffect(() => {
    if (localStorage.getItem("loggedIn") === "true") {
        setLoggedIn(true);
    }
    else {
        setLoggedIn(false);
    }
}, [])

There will be a moment where loggedIn is false.

You could just do:

const [loggedIn, setLoggedIn] = useState(localStorage.getItem("loggedIn") === "true");

and it should avoid the issue.

Upvotes: 1

Related Questions