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

React.useId() usage results in hydration mismatch #43033

Closed
1 task done
rijk opened this issue Nov 17, 2022 · 6 comments · Fixed by #43617
Closed
1 task done

React.useId() usage results in hydration mismatch #43033

rijk opened this issue Nov 17, 2022 · 6 comments · Fixed by #43617
Labels
area: app App directory (appDir: true) Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.).

Comments

@rijk
Copy link

rijk commented Nov 17, 2022

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

next info:
    Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:15:52 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8112
    Binaries:
      Node: 16.18.1
      npm: 8.19.2
      Yarn: N/A
      pnpm: N/A
    Relevant packages:
      next: 13.0.4-canary.3
      eslint-config-next: 13.0.2
      react: 18.2.0
      react-dom: 18.2.0

What browser are you using? (if relevant)

Chrome 107.0.5304.110 (Official Build) (arm64)

How are you deploying your application? (if relevant)

Vercel (not relevant though)

Describe the Bug

Related to #30876, perhaps a regression.

When using React.useId() from a client component, React throws a hydration error:

'use client'

import { useId } from 'react'

export default function IdCheck() {
  const id = useId()
  return <div id={id}>ID: {id}</div>
}
Error: Hydration failed because the initial UI does not match what was rendered on the server.

See more info here: https://nextjs.org/docs/messages/react-hydration-error

This causes issues in libraries like Headless UI: tailwindlabs/headlessui#1961

Expected Behavior

No error.

Link to reproduction - Issues with a link to complete (but minimal) reproduction code will be addressed faster

https://codesandbox.io/s/cool-shannon-duxx1w?file=/app/page.tsx

To Reproduce

Note that I couldn't get the Sandbox to run because the app directory requires node 16 and Codesandbox uses node 14.

@rijk rijk added the bug Issue was opened via the bug report template. label Nov 17, 2022
@SukkaW
Copy link
Contributor

SukkaW commented Nov 17, 2022

I can reproduce the issue locally.

The issue might be caused by Next.js rendering a different tree between the Server and the Client since the return value of useId is determined by the position of a node in the React tree.

@balazsorban44
Copy link
Member

balazsorban44 commented Nov 17, 2022

Weirdly, I cannot reproduce this. 👀 @SukkaW did you use the above reproduction only locally, or have you created a different one? Could you share a link to a GitHub repository? I want to verify this.

@balazsorban44 balazsorban44 added area: app App directory (appDir: true) type: needs investigation labels Nov 17, 2022
@stephanvane
Copy link

It seems to happen when components using useId() are nested. For example, this component triggers the error for me:

"use client";
import { useId } from "react";

const ParentUseId = () => {
  const myId = useId();

  return (
    <div>
      {myId} <ChildUseId />
    </div>
  );
};

const ChildUseId = () => {
  const myId = useId();

  return <>{myId}</>;
};

export default ParentUseId;

I don't have time right now to provide a full repo, but if necessary, I could do this in the weekend :)

@balazsorban44 balazsorban44 added kind: bug and removed bug Issue was opened via the bug report template. labels Nov 18, 2022
@gnoff
Copy link
Contributor

gnoff commented Nov 19, 2022

I've repro'd, It's a bug in React's StrictMode behavior in Dev. Will fix upstream

@balazsorban44 balazsorban44 added Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.). and removed type: needs investigation labels Nov 19, 2022
gnoff added a commit to facebook/react that referenced this issue Nov 28, 2022
In `<StrictMode>` in dev hooks are run twice on each render.

For `useId` the re-render pass uses the `updateId` implementation rather
than `mountId`. In the update path we don't increment the local id
counter. This causes the render to look like no id was used which
changes the tree context and leads to a different set of IDs being
generated for subsequent calls to `useId` in the subtree.

This was discovered here: vercel/next.js#43033

It was causing a hydration error because the ID generation no longer
matched between server and client. When strict mode is off this does not
happen because the hooks are only run once during hydration and it
properly sees that the component did generate an ID.

The fix is to not reset the localIdCounter in `renderWithHooksAgain`. It
gets reset anyway once the `renderWithHooks` is complete and since we do
not re-mount the ID in the `...Again` pass we should retain the state
from the initial pass.
@mzavattaro
Copy link

mzavattaro commented Nov 29, 2022

I can replicate this bug on my end as well whilst using HeadlessUI in my repo and also in the examples here. I'm currently using 13.0.6-canary-1.

Edit: the bug also occurs on production, but is minified by React.

@huozhi huozhi mentioned this issue Dec 2, 2022
3 tasks
ijjk pushed a commit that referenced this issue Dec 2, 2022
Fixes #43033

Also remove the unsued react-dom files: bundles for bun, and
react-dom-test-utils

x-ref: facebook/react#25713

## Bug

- [x] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)
@github-actions
Copy link
Contributor

github-actions bot commented Jan 1, 2023

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: app App directory (appDir: true) Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.).
6 participants