将next-usquerystate与Next JS一起使用时发生水合错误

62lalag4  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(93)

我正在运行next-usequerystate本身的npm page上列出的一个非常简单的示例。
代码如下:

import { useQueryState } from 'next-usequerystate'

export default () => {
  const [name, setName] = useQueryState('name')
  return (
    <>
      <h1>Hello, {name || 'anonymous visitor'}!</h1>
      <input value={name || ''} onChange={e => setName(e.target.value)} />
      <button onClick={() => setName(null)}>Clear</button>
    </>
  )
}

我不会添加或更改任何代码。在第一次加载时,它工作得很好。它应该将状态存储在URL本身中。URL更改以反映状态刚刚好,但当我尝试加载URL中提到的状态的网站时。我得到这个错误。

Unhandled Runtime Error
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

Call Stack
updateHostRoot
node_modules/react-dom/cjs/react-dom.development.js (19849:0)
beginWork
node_modules/react-dom/cjs/react-dom.development.js (21615:0)
beginWork$1
node_modules/react-dom/cjs/react-dom.development.js (27426:0)
performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js (26557:0)
workLoopSync
node_modules/react-dom/cjs/react-dom.development.js (26466:0)
renderRootSync
node_modules/react-dom/cjs/react-dom.development.js (26434:0)
recoverFromConcurrentError
node_modules/react-dom/cjs/react-dom.development.js (25850:0)
performConcurrentWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js (25750:0)
workLoop
node_modules/scheduler/cjs/scheduler.development.js (266:0)
flushWork
node_modules/scheduler/cjs/scheduler.development.js (239:0)
MessagePort.performWorkUntilDeadline
node_modules/scheduler/cjs/scheduler.development.js (533:0)
6jygbczu

6jygbczu1#

面对同样的问题。一个对我有效的修复方法是确保Next.js路由器在渲染之前已经准备好了。
_app.tsx中:

// src/pages/app.tsx

import { useRouterReady } from "@/hooks/useRouterReady";

export default function App({ Component, pageProps }: AppProps) {
  const isRouterReady = useRouterReady();
  return (
      {isRouterReady ? <Component {...pageProps} /> : null}
  );

其中useRouterReady是一个受this guide启发的自定义钩子:

// src/hooks/useRouterReady.ts

import { useState, useEffect } from "react";
import { useRouter } from "next/router";

export const useRouterReady = () => {
  const [isReady, setIsReady] = useState(false);
  const router = useRouter();

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

  return isReady;
};

相关问题