Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First layout not working on Next.js 14.2.23 - react-dom.development.js:17497 Uncaught Error: Element type #165

Open
LrLamonier opened this issue Feb 24, 2025 · 4 comments

Comments

@LrLamonier
Copy link

My project uses libraries that are not ready for React 19, therefore I am using React 18, Next.js v. 14.2.23, React Three Fiber 8.17.10, and React Three uikit 0.8.4.

When trying to reproduce the first layout example

<Suspense fallback={null}>
    <Canvas
        style={{
          position: "fixed",
          width: "100%",
          height: "100vh",
          top: 0,
          left: 0,
        }}
        gl={{ localClippingEnabled: true }}
    >
        <Root sizeX={2} sizeY={1} flexDirection="row">
            <Container flexGrow={1} backgroundColor="red" />
        </Root>
    </Canvas>
</Suspense>

I get the following error:

Image

The component is a client component with "use client";.

The problem still occurs in a brand new Next project.

What am I doing wrong?

@bbohlender
Copy link
Contributor

Can you check whether its related to uikit or r3f in general by removing the uikit elements and just adding a simple ?

@LrLamonier
Copy link
Author

It is uikit related. The tests I did:

  1. Just the canvas - no error
  2. Canvas with a basic object (mesh, box geometry, basic material) - no error
  3. Canvas with an imported gltf model - no error
  4. Canvas with only a <Root /> component - error
  5. The snippet above - error

The crazy thing is that the page actually displays the components correctly, but there is the uncaught error.

Next.js sometimes throws hydration warnings that, in this context, are not a problem since I am actively doing everything on the client. But they’re just warnings. This is an actual error though.

I tried putting it inside its own <Suspense /> boundary. No success.

I tried rendering it conditionally by having an isActive state like so:

const [isActive, setIsActive] = useState(false);

return (
    <Canvas onPointerDown={() => setIsActive(true)}>
        {isActive ?
            <Root></Root>
         : null}
        </Root>
    </Canvas>
)

But it also threw the error even before the component was rendered. When clicking the canvas the content shows up properly.

@bbohlender
Copy link
Contributor

I am not really an expert on nextjs so I have no intuition here. I'd recommend sharing a repo, so I can check your setup myself

@LrLamonier
Copy link
Author

While creating the repo I found where the issue is happening.

TL;DR: the error is thrown when the UI component is inside a <Suspense /> boundary that is inside a server component.

The structure of the page where I am displaying the content is:

<section>
  <Suspense>
    <Canvas>
      <UiComponent />
    </Canvas>
  </Suspense>
</section>

This structure is divided in two:
. <section /> is a server component, meaning it is rendered in the server
. all the rest is Three-related and must be client components

So the division is:

<section>
  <Suspense>
//// server ////

//// client ////
    <Canvas>
      <UiComponent />
    </Canvas>
//// client ////

//// server ////
  </Suspense>
</section>

In this setup a hydration error is thrown. However, if the suspense is moved into the client component, it works.

<section>
//// server ////

//// client ////
  <Suspense> // suspense in the client component
    <Canvas>
      <UiComponent />
    </Canvas>
  </Suspense>
//// client ////

//// server ////
</section>

As for why this happens, I have no idea. And still I was not being able to reproduce the solution in my project. It turns out that Next.js has an application-wide suspense boundary if you create a component in the loading.tsx file. There's an error even if loading is a client component, because it is merely a fallback, not the boundary itself.

I created a repo with code to reproduce the error happening in the two ways I described above as well as the expected behavior.
Right here -> https://github.com/LrLamonier/nextjs-uikit-hydration-error

In the README there are detailed instructions on how to run the project and observe the error.

It is very, very specific, so if my explanation wasn't very good please tell me so I can try and elaborate on whatever's not clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants