Chrome扩展使用上下文处理认证与订阅逻辑时页面显示异常如何解决
问题产生原因
- 加载状态判断逻辑失效:AuthProvider 中加载判断条件为
pending && helper,但helper初始值为 false 且全程无修改逻辑,导致异步请求订阅状态的过程中不会展示加载组件,直接渲染了路由子元素。 - 订阅状态初始值歧义:
subscriptionStatus初始值为null,和“未订阅”状态的判断逻辑混淆。初始加载阶段subscriptionStatus为null时,PrivateRoute 会直接判定为未订阅,触发跳转至订阅页;等异步请求返回用户为已订阅后,又会渲染主页组件,时序冲突导致两个页面同时展示。 - 上下文状态暴露不全:AuthContext 没有把
pending状态传递给下游组件,PrivateRoute 无法感知当前是否处于异步请求状态,只能基于未初始化的状态做路由判断。
修复步骤
1. 修复 AuthProvider 逻辑
修改加载判断、补充未登录场景的状态处理、明确订阅状态的取值、把pending状态加入上下文:
export const AuthProvider = ({ children }) => { const [currentUser, setCurrentUser] = useState(null); const [pending, setPending] = useState(true); const [emailVerified, setEmailVerified] = useState(true); const [subscriptionStatus, setSubscriptionStatus] = useState(null); useEffect(() => { app.auth().onAuthStateChanged(async(user) => { setCurrentUser(user); // 处理未登录场景 if (!user) { setPending(false); return; } if(!user.emailVerified){ setEmailVerified(false); setPending(false); }else{ setEmailVerified(true); const fetchData = async () => { const token = await user.getIdToken(); const payloadHeader = { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, }; const status = await fetch('http://localhost:3000/is-subscribed', payloadHeader).then(r => r.json()); // 明确设置订阅状态,未订阅时设为false,避免和初始null混淆 setSubscriptionStatus(status === 'active' ? status : false); setPending(false); } fetchData(); } }); }, []); // 去掉无效的helper判断,pending时直接展示加载器 if (pending) { return <Loader />; } if(!emailVerified){ return <>Please verify your email</> } return ( <AuthContext.Provider value={{ currentUser, subscriptionStatus, pending // 把pending状态传递到上下文 }} > {children} </AuthContext.Provider> ); };
2. 修复 PrivateRoute 逻辑
新增pending状态判断,加载阶段不做路由跳转,避免误判:
const PrivateRoute = ({ component: RouteComponent, ...rest }) => { const { currentUser, subscriptionStatus, pending } = useContext(AuthContext); // 加载中直接返回加载器,不执行路由判断 if (pending) return <Loader />; return ( <Route {...rest} render={(routeProps) => !!currentUser ? ( !!subscriptionStatus ? ( <RouteComponent {...routeProps} /> ) : ( <Redirect to={"/subscribe"} /> ) ) : ( <Redirect to={"/login"} /> ) } /> ); };
3. 额外校验
确认 /subscribe 路由没有使用 PrivateRoute 包裹,避免未订阅用户进入跳转死循环。
内容的提问来源于stack exchange,提问作者axfg
相关产品推荐
相关产品推荐

