在主应用程序中,我有一个useEffect
挂钩,它将检查用户是否登录:
useEffect(() => {
auth.onAuthStateChanged((user) => {
if (user) {
// User is signed in.
dispatch(
setUser({
name: user.displayName,
email: user.email,
})
);
} else {
// No user is signed in.
}
});
}, [dispatch]);
这是从我的用户缩减器setUser
调用一个操作来存储用户信息。在刷新时,或者如果说我转到了Dashboard页面,我希望它在用户登录时显示该页面,如果没有登录,则re-direct
显示到主页。
现在我正在更改窗口位置以进行测试,但我认为这不是正确的方式?因为它不会存储在浏览器历史记录中,是吗?不管怎么说,这是另一个问题
在加载时,用户为null,因此即使用户登录,它也在运行重定向。我该如何编写它,以等待firebase检查用户是否首先存在-我是否必须在该组件中直接使用auth state change
,而不是使用选择器?我的应用程序中的其他地方也是如此?我想我可能是在写这个问题的时候自己想出来的。这是最好的方式吗?可能是一个返回用户的自定义钩子?
下面是仪表板页面:
import Section from "../components/Section/Section";
import Container from "../components/Container/Container";
import { useSelector } from "react-redux";
import { userInfo } from "../store/slices/user";
const Dashboard = () => {
const user = useSelector(userInfo);
const html = user ? (
<Section>
<Container>
<h1>Dashboard</h1>
<p>If you can see this then you are logged in</p>
</Container>
</Section>
) : (
(window.location.href = "/")
);
return html;
};
export default Dashboard;
感谢
登录挂起状态
我认为选择是好的,但你需要在你的商店有额外的信息,告诉你是否有人正在登录
在应用程序中的某个时刻,您正在调用一个登录方法,该方法是一个需要时间执行的async
函数。我不确定你是否在await
中得到结果。最终,auth
的内部状态将发生变化,来自useEffect
的onAuthStateChanged
回调将把用户对象dispatch
发送到商店。
我建议添加一个dispatch
,它在登录一开始就向您的商店发送某种PENDING_LOGIN
操作。在商店的某个地方,您可以保存boolean
isLoggingIn
或enum
loginState
。
您可以更改登录处理程序:
const handleLogin = async () => {
// immediately dispatch the pending login
dispatch({type: "PENDING_LOGIN" });
const {user} = await await auth.signInAnonymously();
// could dispatch `setUser` action from here instead of from `useEffect`, if you want to
}
在Dashboard
组件中,您可以从您的商店访问此新信息。
const Dashboard = () => {
const user = useSelector(userInfo);
const isLoggingIn = useSelector(someSelector);
if ( ! user && ! isLoggingIn ) {
window.location.href = "/";
}
return (
<Section>
<Container>
<h1>Dashboard</h1>
{user
? <p>If you can see this then you are logged in</p>
: <p>Logging in...</p>
}
</Container>
</Section>
)
};
窗口位置
更改window.location
实际上会将URL添加到历史记录中。以下是MDN的一些信息。
关于将字符串值设置为window.location
:
每当为location对象分配新值时,就会使用URL加载文档,就好像使用修改后的URL调用了location.assign()一样。
关于此assign()
方法:
Location.assign()方法使窗口加载并显示指定URL处的文档。导航发生后,用户可以通过按"键导航回名为Location.assign()的页面;背面";按钮
如果您想导航到一个页面而不将其添加到历史记录中,则有一个单独的方法。
Location接口的replace()方法将当前资源替换为所提供URL处的资源。与assign()方法的区别在于,使用replace()后,当前页面将不会保存在会话历史记录中,这意味着用户将无法使用后退按钮导航到它