【发布时间】:2021-10-06 20:41:11
【问题描述】:
我有一个使用 firebase 进行身份验证的简单反应应用程序。使用 firebase 的问题是,我需要等待 onAuthStateChanged 回调触发,然后才能确定用户是否登录,这只需要一秒钟左右。
我想显示该时间段的加载消息,以便当应用程序显示给用户时,我可以确定我们已经确定了用户。触发回调并且我们为用户确定了状态后,加载应用程序。
下面代码的问题在于,loading 的值从 false 更改为 true 的速度似乎比 onAuthStateChanged 回调被触发的速度快,这意味着应用程序的加载速度比我们有确定的状态要快用户。因此,如果有人导航到仪表板,则尽管用户实际已登录,但仍会首先触发登录的重定向。
我真的需要能够设置像displayApp 这样在回调中设置为true 的变量。但是,如果我这样做,我会收到一条错误消息,提示
从 React Hook useEffect 内部对 'displayApp' 变量的分配将在每次渲染后丢失。
这是有道理的,因为每次都会重新渲染组件并且值会丢失。
在这种情况下保持变量的最佳方法是什么,以便我只能在回调触发后显示我的应用程序?
const auth = firebase.auth();
const AuthStateContext = React.createContext(undefined);
function App() {
const user = useFirebaseAuth();
const [value, loading] = useAuthState(auth);
console.log("Loading: ", loading);
let displayApp = false;
useEffect(() => {
firebase.auth().onAuthStateChanged(authUser => {
console.log("Auth user:", authUser);
console.log("Loading (auth): ", loading);
displayApp = true;
})
})
return (
<>
{!loading &&
<Switch>
<Route path="/" exact>
{user ? <Dashboard/> : <Login/> }
</Route>
<Route path="/dashboard">
<Dashboard/>
</Route>
<Route path="/login">
<Login/>
</Route>
</Switch>
}
{loading &&
<h4>Loading...</h4>
}
</>
)
}
export default function Dashboard(props){
const auth = firebase.auth();
const user = useFirebaseAuth();
console.log("Dashboard");
if(!user){
return (
// <h4>Not logged</h4>
<Redirect to="/login"/> //Since the app is loaded before the user is retrieved, this gets triggered despite the user being logged in
)
}
return (
<>
<h1>Dashboard</h1>
<h4>{auth.currentUser?.displayName}</h4>
<button onClick={() => firebase.auth().signOut()}>Sign out</button>
</>
)
}
【问题讨论】:
-
不要持久化到变量中。这就是错误消息试图告诉您的内容。相反,坚持一些共享状态(可能是 redux 存储),当更新时,会导致组件重新渲染。
-
@DougStevenson 我还在学习反应,所以还没有使用 redux。但是我已经设法通过使用 chrome 本地存储来完成该行为。我假设 redux 可以同步检索?
标签: reactjs firebase firebase-authentication