gpt4 book ai didi

javascript - 加载页面时 Firebase auth.currentUser 为 null,页面加载几毫秒后调用 authstatechange 时加载用户

转载 作者:行者123 更新时间:2023-11-28 16:49:12 26 4
gpt4 key购买 nike

我正在使用 React 和 Firebase 来开发一个小型 Web 应用。为了进行身份验证,我使用上下文 API,并在上下文内添加登录用户详细信息。

AuthProvider.tsx

const AuthProvider: React.FC = props => {
const [state, setState] = useState<IAuthContext>(authInitialState);
console.log("Inside AuthProvider");
useEffect(() => {
auth.onAuthStateChanged( user => {
console.log("Auth State changed and user is ----->", user);
if (user) {
console.log("User value updated to the context")
setState({
...authInitialState,
isAuthenticated:!!user,
permissions:[],
user:user
});
}
const stateChange = {
...authInitialState,
isAuthenticated: !!user,
user
};
// if (!user) {
return setState(stateChange);
// }
});
}, []);
console.log("Rendering AuthProvider", state);
return (
<AuthContext.Provider value={state}>{props.children}</AuthContext.Provider>
);
};
export default AuthProvider;

AuthConsumer.tsx

const withAuthContext = (
Component: React.ComponentClass<any> | React.FunctionComponent<any>
) => {
console.log("Rendering AuthConsumer for ");
return (props: any) => (
<AuthContext.Consumer>
{context => <Component {...props} context={context} />}
</AuthContext.Consumer>
);
};

export default withAuthContext;

PrivateRoute.tsx

interface PrivateRouteProps extends RouteProps {
// tslint:disable-next-line:no-any
component: any;
context: IAuthContext;
}

const PrivateRoute = (props: PrivateRouteProps) => {
const { component: Component, context: IAuthContext, ...rest } = props;
console.log("Private route for ", props);
return (
<Route
{...rest}
render={(routeProps) =>
props.context.isAuthenticated ? (
<Component {...routeProps} />
) : (
<Redirect
to={{
pathname: '/login',
state: { from: routeProps.location }
}}
/>
)
}
/>
);
};

export default withAuthContext(PrivateRoute);

App.tsx

return (
<BrowserRouter>
<div>
<Switch>
<PublicRoute path="/frame" component={Frame} exact isAuthorized={true}/>
<Route path="/login" component={NewLogin} exact isAuthorized={true}/>
<PrivateRoute path="/nav" component={NavigationBar} exact/>
<PrivateRoute path="/dashboard" component={AnalyticsDashBoard} exact/>
<PrivateRoute path="/subscription" component={OrderSuccess} exact/>
<PrivateRoute path="/onboarding" component={OnBoarding} exact/>
</Switch>
</div>
</BrowserRouter>
);

用户已登录,并且 session 持久性设置为本地。问题是,当我尝试 localhost/subscription(这是一条私有(private)路由)时, context.isAuthenticated 为 false,因为“onAuthStateChanged”观察者尚未触发,因此它会进入登录页面,但在几毫秒内,authStateChange 被触发并设置了上下文,但它没有用,因为应用程序已经导航到登录,因为 privateroute 认为用户未登录。我想了解如何克服这个问题。

最佳答案

页面加载时,Firebase 会从本地存储中恢复用户的凭据,并检查服务器是否仍然有效。由于这是对服务器的调用,因此可能需要一些时间并且异步发生。这就是在 onAuthStateChanged 触发之前 firebase.auth().currentUsernull 是正常的原因。

您遇到的问题是 firebase.auth().currentUser 可能为 null 有多种原因:

  1. firebase.auth().currentUsernull,因为客户端刚刚加载,并且仍在与服务器检查凭据。
  2. firebase.auth().currentUsernull,因为客户端根据服务器检查了凭据,并且客户端未登录。
  3. firebase.auth().currentUsernull,因为用户从未登录,因此无需检查凭据。

您想要在情况 2 和 3 中导航,但不想在情况 1 中导航。

典型的解决方案是在第一次触发 onAuthStateChanged 之前不处理导航。此时,您可以确定已根据服务器检查了凭据,或者没有要检查的凭据,在这两种情况下,您都需要导航到登录页面。

<小时/>

加快速度的另一个选项是,当用户首次登录时,自己在本地存储中存储一个小 token ,然后在应用加载时读取该 token 。如果存在 token ,您可以区分情况 1 和 3,并使用它更快地导航到正确的页面。

有关此示例,请参阅此 I/O 讨论 Architecting Mobile Web Apps .

关于javascript - 加载页面时 Firebase auth.currentUser 为 null,页面加载几毫秒后调用 authstatechange 时加载用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60149287/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com