React-Firebase中正确使用onAuthStateChange处理Token过期问题
解决React-Firebase项目中Token自动过期需刷新页面的问题
核心问题分析
你当前的代码仅在组件挂载时通过onAuthStateChanged获取一次Token,但Firebase ID Token每小时自动过期,且onAuthStateChanged仅在用户登录/退出状态变更时触发,不会监听Token刷新事件,因此必须手动刷新页面才能获取新Token。
解决方案
使用Firebase提供的onIdTokenChanged监听Token变化,它会在用户登录状态变更和Token自动刷新时触发回调,无需依赖页面刷新。同时正确清理监听器避免内存泄漏。
修改后的代码
useEffect(() => { // 订阅Token变化监听 const unsubscribe = auth.onIdTokenChanged(async (user) => { if (user) { // 获取最新Token,true表示强制刷新(可选,不传则取当前有效缓存Token) const token = await user.getIdToken(true); const { displayName, email, photoURL, phoneNumber, uid } = user; const userData = { displayName, email, photoURL, phoneNumber, uid }; createUserDocument(userData); // 更新本地存储与应用状态 localStorage.setItem("name", displayName); localStorage.setItem("email", email); localStorage.setItem("phoneNumber", phoneNumber); localStorage.setItem("auth", true); localStorage.setItem("token", token); localStorage.setItem("photoURL", photoURL); setPhotoUrl(photoURL); dispatch({ type: UPDATE_USER, payload: userData }); } else { // 用户退出时清理状态(按需调整) localStorage.removeItem("name"); localStorage.removeItem("email"); localStorage.removeItem("phoneNumber"); localStorage.removeItem("auth"); localStorage.removeItem("token"); localStorage.removeItem("photoURL"); setPhotoUrl(null); dispatch({ type: CLEAR_USER }); } }); // 组件卸载时取消订阅,避免内存泄漏 return unsubscribe; }, [dispatch]);
关键细节说明
onIdTokenChanged:替代onAuthStateChanged,覆盖Token刷新场景,确保每次Token更新都能自动获取新值。user.getIdToken(true):强制Firebase刷新Token并返回最新值,确保传递给后端的Token始终有效;若不需要强制刷新,可省略true参数,获取当前缓存的有效Token。- 监听器清理:返回
unsubscribe函数,React会在组件卸载或依赖变更时自动执行,防止无效监听导致的性能问题。 - 依赖数组:仅传入
dispatch(Redux的useDispatch返回的函数引用稳定),不会引发不必要的重渲染。
内容的提问来源于stack exchange,提问作者Sushanth
相关产品推荐
相关产品推荐

