如何在 React 应用程序中使用 firebase onAuthStateChange 和 React router dom RouterProvider API 保持用户在刷新仪表板页面时保持登录状态

问题描述 投票:0回答:1

我正在使用react router dom RouterProvider,它将获取与渲染分离,来自auth-router-provider的官方remix-run React Router示例,在

README.md
中指出

我们不能再依赖 React 上下文和/或钩子来获取用户身份验证状态。我们需要在 React 树之外访问这些信息,以便我们可以在路由加载器和操作函数中使用它。 https://github.com/remix-run/react-router/tree/dev/examples/auth-router-provider

我在 React 树之外创建了一个独立的对象,用于管理我的身份验证状态

login and logout
,我的对象结构如下所示

export const authProvider: AuthProvider = {
  user: null,

  async login(email: string, password: string) {
    return signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        authProvider.user = userCredential.user;
        return redirect("/dashboard");
      })
      .catch(() => {
        return toast.error("Password or Email invalid");
      });
  },

  async signout() {
    signOut(auth);
    authProvider.user = null;
  },
};

我导入独立对象我的加载程序文件并在我的仪表板加载程序中返回

authProvider.user

loader() {
  return { user: authProvider.user };
}

用户可以使用仪表板组件中的

useRouteLoaderData
进行访问

const {user} = useRouteLoaderData("dashboard")

用户最初将为空,如果用户未登录,我可以导航到其他位置,但是当用户登录时,用户不再为空并且可以查看仪表板页面,但是当我在用户登录用户总是返回null。

我似乎无法正确使用 firebase 中的

onAuthStateChange
,因为之前当我使用 React 上下文管理用户时,我在
useEffect
中使用了它。

我需要有关如何让用户坚持刷新仪表板页面的帮助。

reactjs firebase-authentication react-router-dom dataloader
1个回答
0
投票

更新您的

authProvider
对象以包含一个可以调用 Firebase 的
onAuthStateChanged
函数来检查当前用户的身份验证状态的函数。将调用包装在 Promise 中,该 Promise 在
onAuthStateChanged
成功时解析,或者在失败情况下拒绝。

import {
  getAuth,
  onAuthStateChanged,
  signInWithEmailAndPassword,
  signOut,
} from "firebase/auth";

const auth = getAuth();

interface AuthProvider {
  user: User | null;
  checkAuth(): Promise<void>;
  login(email: string, password: string): Promise<void>;
  signout(): Promise<void>;
}

export const authProvider: AuthProvider = {
  user: null,

  checkAuth: async () => {
    return new Promise((resolve, reject) => {
      onAuthStateChanged(
        auth,
        (user) => {
          authProvider.user = user; // User | null
          resolve();
        },
        reject
      );
    });
  },
  login: async (email: string, password: string) => {
    return signInWithEmailAndPassword(auth, email, password)
      .then((userCredential) => {
        authProvider.user = userCredential.user;
        return redirect("/dashboard");
      })
      .catch(() => {
        return toast.error("Password or Email invalid");
      });
  },
  signout: async () => {
    signOut(auth);
    authProvider.user = null;
  },
};

调用您的

authProvider
实例的
checkAuth
函数并等待其稳定。

loader = async () => {
  try {
    await authProvider.checkAuth();
    return {
      user: authProvider.user
    };
  } catch(error) {
    // handle/ignore error
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.