Next.js Discord

Discord Forum

Hydration errors in client components' content?

Unanswered
declspecl posted this in #help-forum
Open in Discord
I thought that if I mark a component with the "use client" directive, I am telling (and forcing) Next to render that on the client side and explicitly NOT the server. My component also uses useState, useMemo, and useEffect, making it impossible to even render on the server. But for some reason, I am getting hydration errors for JSX/HTML inside that component due to me using a useMediaQuery to show different content on mobile and desktop. My structure basically looks like this in pseudocode
<ServerComponent>
  const data = await getData();

  <ClientComponentA data={data}>
    "use client";

    <ClientComponentB>
      "use client";

      <ClientComponentC>
        "use client";

        const state = useState(...);
        const memo = useMemo(() => ...);
        const isDesktop = useMediaQuery("...");

        {/* HYDRATION ERROR BELOW */}

        {isDesktop ? (

        ) : (

        )}
      </ClientComponentC>
    </ClientComponentB>
  </ClientComponentA>
</ServerComponent>

A few questions:
- Am I misunderstanding client components and/or how next hydrates?
- How is it even possible to get hydration errors for client components? Especially for client components in client components in client components etc.
- Is there a way to FORCE next to ONLY render it client side, when multiple client side hooks and directives don't work?

8 Replies

Also important note is that each component's children is contained in the component itself - meaning ClientComponentB is contained in the ClientComponentA code; it's not passed as a of ClientComponentA from ServerComponent. This is true for each component
And plus, I get the hydration error but my app still works correctly and renders as expected. Next logs the error in the console and switches to client side rendering, which is what I wanted to begin with. I also checked the server returned HTML and it's as I want - none of the client components are included in the HTML. So it seems like the issue is with the actual hydration strategy rather than a mismatch between the server and client HTML?
Nope @declspecl
Your understanding is incorrect
"use client" indicates entry point of client boundary
client coponents are still rendered on the server and hydrates to the client end
if you want to have your component rendered on your client, you can use dynamic loading with ssr: false or client-only
@declspecl I thought that if I mark a component with the `"use client"` directive, I am telling (and forcing) Next to render that on the client side and explicitly NOT the server. My component also uses `useState`, `useMemo`, and `useEffect`, making it impossible to even render on the server. But for some reason, I am getting hydration errors for JSX/HTML inside that component due to me using a `useMediaQuery` to show different content on mobile and desktop. My structure basically looks like this in pseudocode jsx <ServerComponent> const data = await getData(); <ClientComponentA data={data}> "use client"; <ClientComponentB> "use client"; <ClientComponentC> "use client"; const state = useState(...); const memo = useMemo(() => ...); const isDesktop = useMediaQuery("..."); {/* HYDRATION ERROR BELOW */} {isDesktop ? ( ) : ( )} </ClientComponentC> </ClientComponentB> </ClientComponentA> </ServerComponent> A few questions: - Am I misunderstanding client components and/or how next hydrates? - How is it even possible to get hydration errors for client components? Especially for client components in client components in client components etc. - Is there a way to FORCE next to ONLY render it client side, when multiple client side hooks and directives don't work?
Am I misunderstanding client components and/or how next hydrates?

Yes, as james said use client defines an entry point into a client boundary meaning any components imported into that boundary will be client components (this does not include the children prop only explicit imports)

How is it even possible to get hydration errors for client components? Especially for client components in client components in client components etc.

When using use client the HTML (JSX in this case) is pre-rendered on the server, but, because you are conditionally rendering different HTML based on the isDesktop property, when the client hydrates and that value actually exists the HTML is most likely rendered different than what the server passed to the client initally.

Is there a way to FORCE next to ONLY render it client side, when multiple client side hooks and directives don't work?

Yes there is, you can use can import dynamic from "next/dynamic" and dynamically import that component and set ssr: false to force that component to render client-side instead of server-side. You can look at an example from the [docs](https://nextjs.org/docs/app/building-your-application/optimizing/lazy-loading#nextdynamic)
I had to do this myself for a my theme toggle component, this is because I am applying certain styles based on a client-side hooks return value, which the server cannot know about which results in a hydration error at runtime, unless I use next/dynamic.

If you care about Suspense you can also pass a loading skeleton to the loading property when dynamically importing with next/dynamic.