How should I handle this hydration error?

80 Views Asked by At

I have a "use client" component that throws hydration errors:

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

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

This is the component:

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>
  );
}

It is supposed to render a button that either navigates you to a new url if you are in a regular browser. But if you are in the embedded browser of a desktop client, it should render a button that opens said url in a new "workspace" in the desktop client.

The isInDesktopClient is zustand-state that is set in a component loaded in the head of the application like so:

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>
  );
}

This is the DesktopClient component, it waits for the desktopPlugin(that lets the embedded browser and the desktop client communicate) to be setup. If it responds it stores the ticket in cookies and sets the zustand-state to true for later use:

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

The "isInDesktopClient" is obviously never true on the server, so the server-rendered html will never match what is in the embeddedbrowser within the desktop client.

How can I do this in a way that doesnt cause hydration errors?

0

There are 0 best solutions below