reactjs 使用React的Firebase身份验证-页面刷新问题

ercv8c1e  于 2023-01-02  发布在  React
关注(0)|答案(2)|浏览(154)

我试图创建一个基本的React与Firebase和Zustand应用程序。有一个登录页面和 Jmeter 板页面。您只能查看 Jmeter 板页面,如果您登录,否则你会被重定向到登录页面。登录后,用户被重定向到 Jmeter 板页面,显示用户的电子邮件ID。问题是,当我登录后刷新 Jmeter 板页面,尽管已登录,我被重定向到登录页面,因为在第一次呈现,用户名是空的。代码是附加的。我如何绕过这个行为?

function App() {
  const userData = useUserStore((state) => state.setUser);
  useEffect(() => {
    const authState = onAuthStateChanged(auth, (user) => {
      if (user) {
        userData(user.email);
      } else {
        console.log("no user");
      }
    });

    return () => {
      authState();
    };
  }, []);

  return <RouterProvider router={router} />;
}
function Dashboard() {
  const username = useUserStore((state) => state.username);

  return username ? (
    <div>Hi, {username}</div>
  ) : (
    <Navigate to="/login" />
  );
}
wbgh16ku

wbgh16ku1#

有几种方法可以解决这个问题。一种方法是使用 Jmeter 板组件中的useEffect钩子来检查用户是否在每次呈现时登录。您可以使用Firebase中的onAuthStateChanged方法来检查用户是否登录。如果用户登录,则您什么也不能做。如果用户未登录,您可以使用@reach/router库中的Navigate组件将用户重定向到登录页面。
下面是一些示例代码,说明如何实现这一点:

function Dashboard() {
  const username = useUserStore((state) => state.username);

  useEffect(() => {
    const authState = onAuthStateChanged(auth, (user) => {
      if (!user) {
        Navigate("/login");
      }
    });

    return () => {
      authState();
    };
  }, [username]); // Only run this effect when the username changes

  return username ? (
    <div>Hi, {username}</div>
  ) : (
    <div>Loading...</div>
  );
}

另一种选择是使用firebase/auth库中的useSession钩子来检查用户是否登录。该钩子将在每次呈现时自动检查用户的登录状态,并相应地更新登录状态。您可以在App组件中使用该钩子,并将登录状态作为属性向下传递到Dashboard组件。
下面是一些示例代码,说明如何实现这一点:

function App() {
  const { user } = useSession();

  return (
    <RouterProvider router={router}>
      <Dashboard user={user} />
    </RouterProvider>
  );
}

function Dashboard({ user }) {
  return user ? (
    <div>Hi, {user.email}</div>
  ) : (
    <Navigate to="/login">Hello</Navigate>
  );
}
fjaof16o

fjaof16o2#

是的,你是对的,给每个经过验证的路由添加useEffect钩子会导致大量的代码重复,避免这种重复的一种方法是创建一个高阶组件(HOC)来为你处理验证检查。
HOC是一个函数,它将组件作为参数,并返回具有某些附加行为的新组件。在这种情况下,您可以创建一个HOC来检查用户是否已登录,如果未登录,则将用户重定向到登录页。然后,您可以使用此HOC来 Package 任何需要验证的路由,验证检查将自动处理。
下面是一些示例代码,说明如何实现这一点:

// auth-hoc.js
import { useEffect } from "react";
import { Navigate } from "@reach/router";
import { onAuthStateChanged } from "firebase/auth";

export default function withAuth(Component) {
  return function AuthenticatedComponent(props) {
    useEffect(() => {
      const authState = onAuthStateChanged(auth, (user) => {
        if (!user) {
          Navigate("/login");
        }
      });

      return () => {
        authState();
      };
    }, []);

    return <Component {...props} />;
  };
}

然后,您可以像这样使用HOC:

import withAuth from "./auth-hoc";

function Dashboard() {
  const username = useUserStore((state) => state.username);

  return username ? (
    <div>Hi, {username}</div>
  ) : (
    <div>Loading...</div>
  );
}

导出默认值with Auth( Jmeter 板);
现在,任何使用withAuth HOC的路由都将受到身份验证检查的保护。这样,您就可以避免在多个地方重复相同的代码。

相关问题