如何检查用户是否被 localStorage 登录并根据它重定向?

How to check if user is logged by localStorage and Redirect according to it?

我是 localStorage 和 React Router 的新手,我的目标是: 登录时将用户重定向到“/dashboard”,注销时重定向回“/home”。当然,如果他没有登录,也不允许他去 'dashboard'。出于某种原因,我在 App.js 中的代码不起作用:

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;

我通过 localStorage.setItem('userLogged', false)localStorage.setItem('userLogged', true)

在主页和控制面板中设置了它

您可以渲染路由并使用 Navigate 组件进行重定向。像这样-

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

无论何时注销,您都需要使用 useNavigate 挂钩手动重定向到所需的页面。

您只能从其他 window/browser 上下文中监听 localStorage 中的更改,而不能从同一 browser/window 上下文中监听。这里期望 window 知道它自己的状态。在这种情况下,您 实际上 需要一些 React 状态。

userLogged 转换为 React 状态变量并使用 useEffect 挂钩来初始化和持久化 userLogged 状态 to/from localStorage。不是有条件地渲染 Route 组件,而是创建一个包装器组件以从 localStorage 读取 userLogged 值,并有条件地为 nested/wrapped 路由 [=32 渲染一个 Outlet =] 或 一个 Navigate 组件重定向到您的身份验证路由以登录。

示例:

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;

首页

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 });
    }
  };

  ...
};