我正在使用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
中使用了它。
我需要有关如何让用户坚持刷新仪表板页面的帮助。
更新您的
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
}
}