基于Next.js路由器渲染内容,查询导致重新渲染和 Flink ?

hc8w905p  于 2023-05-28  发布在  Flink
关注(0)|答案(2)|浏览(204)

我有一个页面使用router.query来确定要呈现的内容。
然而,在加载router.query代码之前,页面似乎总是在没有router.query的情况下呈现,从而导致页面“ Flink ”。
下面是一个简单的stackblitz来说明我的意思:https://stackblitz.com/edit/nextjs-jvtyrm?file=pages/index.js
相关代码位:

export default function Home() {
  const router = useRouter();
  const isRouterQuery = router.query.foo ? true : false;

  return (
    <div className={styles.container}>
      <main className={styles.main}>
        <button
          onClick={() => {
            if (isRouterQuery) {
              window.location.href = '/';
            } else {
              window.location.href = '/?foo=bar';
            }
          }}
        >
          Toggle between homepage and homepage with router.query
        </button>
        {isRouterQuery ? (
          <h1 className={styles.title}>Router Header</h1>
        ) : (
          <h1 className={styles.title}>
            Welcome to <a href="https://nextjs.org">Next.js!</a>
          </h1>
        )}

// ...

如果单击按钮从/切换到/?foo=bar,您将看到初始渲染显示Welcome to Next.js一瞬间,然后重新渲染以显示Router Header内容。
我如何摆脱这种最初的 Flink ?

dl5txlt9

dl5txlt91#

如果一个页面没有数据获取方法, Flink 将总是发生在页面的第一次加载,因为当页面在服务器上由Next.js预生成时,router.query是一个空对象。
next/router文档:
queryObject-解析为对象的查询字符串。如果页面没有data fetching requirements,则在预呈现期间它将是一个空对象。默认为{}
在您的例子中,单击按钮时也会遇到 Flink ,因为您使用window.location.href在页面之间导航,这会导致整个页面重新加载,而不是客户端导航。
要解决这个问题,只需将window.location.href语句替换为router.push调用。这样,Next.js就可以正确地执行客户端导航,而不会触发 Flink 。

<button
    onClick={() => {
        if (isRouterQuery) {
            router.push('/');
        } else {
            router.push('/?foo=bar');
        }
    }}
>
    Toggle between homepage and homepage with router.query
</button>
drkbr07n

drkbr07n2#

路由器现在具有isReady布尔值。我能够通过先检查内容来防止内容 Flink 。
从文档:
isReady:boolean -路由器字段是否已在客户端更新并可供使用。只应在useEffect方法内部使用,而不应用于在服务器上有条件地呈现。
在你的情况下你可以

const router = useRouter();
  const [routerReady, setRouterReady] = useState(false)

  useEffect(() => {
    setRouterReady(router.isReady)
  }, [router.isReady])

  const isRouterQuery = router.query.foo ? true : false;

并在模板中检查它

<button
          onClick={() => {
            if (routerReady && isRouterQuery) {
              window.location.href = '/';
            } else {
              window.location.href = '/?foo=bar';
            }
          }}
        >
          Toggle between homepage and homepage with router.query
        </button>

相关问题