reactjs 页面刷新期间的React Router Maintain状态

lf3rwulv  于 2023-01-25  发布在  React
关注(0)|答案(1)|浏览(126)

正在设置react路由器只显示我的导航栏上的所有路线,除了登录页面。我创建了一个布局组件,处理这一点,并将返回用户登录页面,如果他们没有通过身份验证。我目前存储我的状态到本地存储,如果值为真,用户仍然通过身份验证,可以留在他们的当前页面。这工作很好,虽然当页面刷新,即使本地存储项设置为true,它也会将用户返回到登录页面。对于我可能做错了什么,或者对于我正在尝试完成的工作,有什么建议吗?谢谢。
App.js

export const AuthContext = createContext();

function App() {
  const stillAuth = window.localStorage.getItem("auth state");
  console.log("still auth: " + stillAuth);
  const [isAuthenticated, setIsAuthenticated] = useState(stillAuth);
  console.log("isAuth: " + isAuthenticated);

  return (
    <div className="App d-flex flex-column" style={{ minHeight: "100vh" }}>
      <AuthContext.Provider value={{ isAuthenticated, setIsAuthenticated }}>
        <Routes>
          <Route path="login" element={<Login />} />
          <Route path="/" element={<Layout />}>
            <Route path="/" element={<Home />} />
            <Route path="/DevExamples" element={<DeveloperExamples />} />
            <Route path="/CliExamples" element={<ClientExamples />} />
            <Route path="*" element={<Error />} />
          </Route>
        </Routes>
      </AuthContext.Provider>

      <Footer />
    </div>
  );
}

function Layout() {
  const { isAuthenticated } = useContext(AuthContext);

  if (isAuthenticated != true) return <Navigate to="/login" />;

  return (
    <>
      <NavBar />
    </>
  );
}

export default App;

Login.jsx

const Login = () => {
  const [username, setUserName] = useState("");
  const [password, setPassword] = useState("");

  const navigate = useNavigate();
  const { isAuthenticated, setIsAuthenticated } = useContext(AuthContext);

  const handleLogin = () => setIsAuthenticated(true);
  const handleLogout = () => setIsAuthenticated(false);

  const updateToken = (username, password) => {
    // make axios call and check if username & password are valid
    window.localStorage.setItem("auth state", true);
    handleLogin();
    navigate("/");

    // excluded for now to test and develop
    // LoginService.authLogin({
    //   username: username,
    //   password: password,
    // }).then(() => {
    // });
  };

  return (
    <div>
      <h1>Please Log In</h1>
      {/* <form onSubmit={handleSubmit}> */}
      <label>
        <p>Username</p>
        <input
          type="text"
          onChange={(e) => setUserName(e.target.value)}
          value={username}
          required
        />
      </label>
      <br />
      <label>
        <p>Password</p>
        <input
          type="password"
          onChange={(e) => setPassword(e.target.value)}
          value={password}
          required
        />
      </label>
      <div>
        <button
          // component={Link}
          // to="/home"
          onClick={() => updateToken(username, password)}
        >
          <Link to="/">Sign In</Link>
        </button>
      </div>
      {/* </form> */}
    </div>
  );
};

Sandbox

guz6ccqo

guz6ccqo1#

问题

这里的问题是存储到localStorage中的值是字符串化的。

window.localStorage.setItem("state", true);
const state = window.localStorage.getItem("state"); // "true"

一旦布尔"auth state"值保存到localStorage中,它就变成了字符串文字,Layout将字符串文字与布尔值进行比较。

console.log("true" != true);  // true
console.log("true" !== true); // true
console.log("false" != true);  // true
console.log("false" !== true); // true

表达式isAuthenticated != true将***总是***计算为真,并且将实现到"/login"的重定向。

溶液

通常,您应该习惯显式地对保存到localStorage的数据进行JSON字符串化和解析。
一个一个二个一个一个一个三个一个一个一个一个一个四个一个
登录

const updateToken = (username, password) => {
  // make axios call and check if username & password are valid
  window.localStorage.setItem("auth state", JSON.stringify(true)); // <-- stringify
  handleLogin();
  navigate("/");

  // excluded for now to test and develop
  // LoginService.authLogin({
  //   username: username,
  //   password: password,
  // }).then(() => {
  // });
};

相关问题