我应该如何处理这个水化错误?

How should I handle this hydration error?

提问人:mTv 提问时间:11/17/2023 更新时间:11/17/2023 访问量:15

问:

我有一个“使用客户端”组件,它会抛出冻结错误:

2 倍Hydration failed because the initial UI does not match what was rendered on the server.

1 倍There was an error while hydrating this Suspense boundary. Switched to client rendering.

这是组件:

export default function NavigationButton(props: NavigationButtonProps) {
  const isInDesktopClient = useDesktopClient((state) => state.isInDesktopClient);

  return isInDesktopClient ? (
    <Button
      {...props}
      variant={props.variant}
      onClick={() => {
        desktopClientPlugin.openInWorkspace(
          `${window.location.origin}/${props.href}`,
          props.title || "",
          props.subTitle,
        );
      }}
    >
      {props.children}
    </Button>
  ) : (
    <Button
      {...props}
      component={Link}
      href={props.href}
      variant={props.variant}
    >
      {props.children}
    </Button>
  );
}

它应该呈现一个按钮,如果您在常规浏览器中,该按钮会将您导航到新 URL。但是,如果您在桌面客户端的嵌入式浏览器中,它应该呈现一个按钮,该按钮在桌面客户端的新“工作区”中打开所述 URL。

在应用程序头部加载的组件中设置的 zustand-state,如下所示:isInDesktopClient

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <head>
        <ColorSchemeScript />
        <DesktopClient />
      </head>
      <body className={`${circularFont.className} bg-neutral-20`}>
        <TRPCProvider>
          <MantineProviders>{children}</MantineProviders>
        </TRPCProvider>
      </body>
    </html>
  );
}

这是组件,它等待desktopPlugin(允许嵌入式浏览器和桌面客户端通信)的设置。如果它响应,它会将票证存储在 cookie 中,并将 zustand-state 设置为 true 以供以后使用:DesktopClient

export default function DesktopClient() {
  useEffect(() => {
    const fetchClientTicket = () => {
      const interval = setInterval(() => {
        if (desktopClientPlugin.isReady()) {
          clearInterval(interval);

          const clientTicket = desktopClientPlugin.getTicket();
          Cookies.set("clientTicket ", clientTicket || "");
          useDesktopClient.setState({ isInDesktopClient: true });
        }
      }, 100);
      return () => clearInterval(interval);
    };
    fetchClientTicket();
  }, []);

  return null;
}

“isInDesktopClient”显然在服务器上永远不会为真,因此服务器呈现的 html 永远不会与桌面客户端中嵌入式浏览器中的内容匹配。

我怎样才能以一种不会导致补水错误的方式做到这一点?

下一个.js next.js13 水化

评论

0赞 mTv 11/17/2023
找到了解决方案。禁用需要检查是否在桌面客户端中的组件的 SSR。 ' dynamic(() => Promise.resolve(NavigationButton), { ssr: false }) '

答: 暂无答案