next.js 当转到上一页时,useState仍然具有旧值

ibrsph3r  于 2023-04-11  发布在  其他
关注(0)|答案(2)|浏览(274)

每个页面都经过一个AuthGuard组件,该组件决定是否可以显示子组件,或者是否需要将用户重定向到另一个页面。
当第一次访问一个页面时,它工作得很好,但是我注意到当返回到前一个页面时有一些奇怪的行为。例如:
1.我没有登录并转到/home,它只显示给登录的用户。我被重定向到/login,这是正确的。
1.我点击浏览器(左上角)进入前一页。请注意,我不是通过点击网站上的链接进入前一页的。
1.在不到一秒钟的时间里,我可以看到/home的内容,然后我被重定向回/login,这是由AuthGuard处理的。
我使用了一个boolean状态钩子来显示子对象,并注意到当返回到前一页时,它仍然设置为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",
    },
  };
}
p4rjhz4m

p4rjhz4m1#

一个简单的解决方案可以实现这一点,方法是观察路由的useEffect,并在路由改变时清除或重置状态
从“next/router”导入{useRouter}
const Page =(props)=〉{
const [state,setState] = useState(someState)
const pageRoute = useRouter().asPath
useEffect(()=〉{ setState(resetState)//当页面路由改变时状态会重置。},[pageRoute])

1yjd4xko

1yjd4xko2#

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

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 />;
  }
  
  ...
};

相关问题