useState在上一页时仍然具有旧值



每个页面都要经过一个AuthGuard组件,该组件决定是否可以显示子组件,或者是否需要将用户重定向到另一个页面。

当第一次访问一个页面时,它工作得很好,但我注意到当返回到前一个页面时,一些奇怪的行为。例如:

  1. 我没有登录,去/home,这只显示登录用户。我重定向到/login,这是正确的。
  2. 我在浏览器中点击(左上角)转到上一页。请注意,我不会通过点击网站上的链接转到上一页。
  3. 不到一秒钟,我可以看到/home的内容,然后我被重定向回/login,这是由AuthGuard处理。

我使用布尔状态钩子来显示孩子,并注意到当返回到上一页时,它仍然被设置为truetrue仍然是加载/login时得到的旧值。为什么不重新开始呢?

我的AuthGuard:

const AuthGuard = ({ children, restriction }) => {
const [canShowChildren, setCanShowChildren] = useState<boolean>(false);
const { user, loading } = useAuth();
const router = useRouter();
// I need to use useEffect & async because some user data can only be retrieved
// asynchronously, though I haven't included that part here because it's 
// irrelevant to the problem.
useEffect(() => {
(async () => {
if (loading || !router.isReady) return;
if (restriction === "public") {
setCanShowChildren(true);
return;
}
if (!user) {
router.push("/login");
return;
}
...
})();
}, [loading, restriction, router, user]);
if (loading || !router.isReady) {
return <Loading />;
}
return canShowChildren ? children : <Loading />;
}

我通过getStaticProps在页面中设置限制,如:

export async function getStaticProps() {
return {
props: {
restriction: "public",
},
};
}

一个简单的解决方案是通过在useEffect中观察路由,当它改变时清除或重置状态

从'next/router'中导入{useRouter}

const Page = (props) =>{

const [state, setState] = useState(someState)

const pageRoute = useRouter().asPath

useEffect(() =比;{setState(resetState)//当页面路由改变时,状态将重置。}, [pageRoute])

我还可以通过在状态钩子中保存路由来让它工作。然而,我认为这是一个肮脏的修复,并希望更多地了解为什么会发生这种情况。

const AuthGuard = ({ children, restriction }) => {
const [canShowChildren, setCanShowChildren] = useState<boolean>(false);
const { user, loading } = useAuth();
const router = useRouter();
const [route, setRoute] = useState<string>("");
useEffect(() => {
(async () => {
if (router.asPath !== route) setCanShowChildren(false);
setRoute(router.asPath);
...
})();
}, [loading, restriction, router, user, pageRoute]);

if (loading || !router.isReady || router.asPath !== route) {
return <Loading />;
}

...
};