Home > Back-end >  How to check if user is logged by localStorage and Redirect according to it?
How to check if user is logged by localStorage and Redirect according to it?

Time:06-02

I am new to localStorage and React Router, and my goal is: Redirect user to the "/dashboard" when he is logged in, and Redirect back to '/home' when he is logged out. Also, of course, not allowing him to go to the 'dashboard' if he is not logged in. For some reason my code in App.js not working:

function App() {
  let userLogged;

  useEffect(() => {
    function checkUserData() {
      userLogged = localStorage.getItem("userLogged");
    }

    window.addEventListener("storage", checkUserData);

    return () => {
      window.removeEventListener("storage", checkUserData);
    };
  }, []);

  return (
    <div className="App">
      <React.StrictMode>
        <Router>
          <Routes>
            <Route path="/" element={<Home />} />
            {userLogged ? (
              <Route path={"/dashboard"} element={<Dashboard />} />
            ) : (
              <Route path={"/home"} element={<Home />} />
            )}
          </Routes>
        </Router>
      </React.StrictMode>
    </div>
  );
}

export default App;

I set it in the home and dashboard pages by localStorage.setItem('userLogged', false) and localStorage.setItem('userLogged', true)

CodePudding user response:

You can only listen to changes in localStorage from other window/browser contexts, not from within the same browser/window context. Here it's expected the window knows its own state. In this case, you actually need some React state.

Convert the userLogged to a React state variable and use a useEffect hook to initialize and persist the userLogged state to/from localStorage. Instead of conditionally rendering Route components, create a wrapper component to read the userLogged value from localStorage and conditionally render an Outlet for nested/wrapped routes or a Navigate component to redirect to your auth route to login.

Example:

import { Navigate, Outlet, useLocation } from 'react-router-dom';

const AuthWrapper = () => {
  const location = useLocation(); // current location

  const userLogged = JSON.parse(localStorage.getItem("userLogged"));

  return userLogged
    ? <Outlet />
    : (
      <Navigate
        to="/"
        replace
        state={{ from: location }} // <-- pass location in route state
      />
    );
};

...

function App() {
  const [userLogged, setUserLogged] = useState(
    JSON.parse(localStorage.getItem("userLogged"))
  );

  useEffect(() => {
    localStorage.setItem("userLogged", JSON.stringify(userLogged));
  }, [userLogged]);

  const logIn = () => setUserLogged(true);
  const logOut = () => setUserLogged(false);

  return (
    <div className="App">
      <React.StrictMode>
        <Router>
          <Routes>
            <Route path="/" element={<Home logIn={logIn} />} />
            <Route path={"/home"} element={<Home logIn={logIn} />} />
            <Route element={<AuthWrapper />}>
              <Route path={"/dashboard"} element={<Dashboard />} />
            </Route>
          </Routes>
        </Router>
      </React.StrictMode>
    </div>
  );
}

export default App;

Home

import { useLocation, useNavigate } from 'react-router-dom';

const Home = ({ logIn }) => {
  const { state } = useLocation();
  const navigate = useNavigate();

  const loginHandler = () => {
    // authentication logic

    if (/* success */) {
      const { from } = state || {};

      // callback to update state
      logIn();
      // redirect back to protected route being accessed
      navigate(from.pathname, { replace: true });
    }
  };

  ...
};

CodePudding user response:

You can render both route and use Navigate component to redirect. Like this -

// [...]
<Route path={"/dashboard"} element={<Dashboard />} />
<Route path={"/home"} element={<Home />} />
{
userLogged ?
<Navigate to="/dashboard" /> :
<Navigate to="/home" />
}
// other routes

Whenever you logout, you need to manually redirect to the desired page using useNavigate hook.

  • Related