React Router RouterProvider中Firebase onAuthStateChange实现刷新保登录
解决React Router RouterProvider下Firebase Auth状态刷新丢失问题
核心问题原因
刷新页面时,authProvider.user初始为null,而Firebase的认证状态需要异步从本地存储恢复,此时loader已执行并返回null,导致页面获取不到有效用户信息。之前在React上下文中用useEffect监听onAuthStateChanged的方式,需要调整为应用启动时就在React树外初始化监听,同时让loader等待认证状态恢复完成。
解决方案代码修改
1. 更新authProvider,添加初始化监听与等待方法
import { getAuth, signInWithEmailAndPassword, signOut, onAuthStateChanged, User } from "firebase/auth"; const auth = getAuth(); interface AuthProvider { user: User | null; login(email: string, password: string): Promise<any>; signout(): Promise<void>; waitForInitialUser(): Promise<User | null>; } export const authProvider: AuthProvider = { user: null, // 用于等待初始用户状态加载完成的Promise _initialUserPromise: null as Promise<User | null> | null, async login(email: string, password: string) { try { const userCredential = await signInWithEmailAndPassword(auth, email, password); authProvider.user = userCredential.user; return redirect("/dashboard"); } catch { toast.error("邮箱或密码无效"); } }, async signout() { await signOut(auth); authProvider.user = null; }, // 初始化认证状态监听 init() { if (!this._initialUserPromise) { this._initialUserPromise = new Promise((resolve) => { const unsubscribe = onAuthStateChanged(auth, (user) => { authProvider.user = user; resolve(user); // 若需要实时同步用户状态变化(如异地登出),可移除unsubscribe() unsubscribe(); }); }); } }, // 供loader调用,等待初始用户状态加载完成 async waitForInitialUser() { if (!this._initialUserPromise) { this.init(); } return this._initialUserPromise; }, };
2. 在应用入口初始化authProvider
在React应用入口文件(如main.tsx)中,启动时调用初始化方法:
import { authProvider } from "./path-to-auth-provider"; // 提前初始化认证状态监听 authProvider.init(); ReactDOM.createRoot(document.getElementById("root")!).render( <React.StrictMode> <RouterProvider router={router} /> </React.StrictMode> );
3. 修改loader,等待用户状态初始化
在仪表板的loader中,先等待认证状态恢复,再返回用户信息:
import { authProvider } from "./path-to-auth-provider"; export async function loader() { const user = await authProvider.waitForInitialUser(); // 用户未登录则重定向到登录页 if (!user) { return redirect("/login"); } return { user }; }
关键说明
onAuthStateChanged在应用启动时触发,会自动从本地存储恢复用户登录状态,同步更新authProvider.user。waitForInitialUser()确保loader不会在用户状态未就绪时返回null,保证刷新页面时能拿到有效用户数据。- 若需要实时监听用户状态变化(如其他设备登出、用户信息更新),可移除
unsubscribe(),保持监听持续生效。
内容的提问来源于stack exchange,提问作者Abdulbasit Yusuf
相关产品推荐
相关产品推荐

