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

Bug: useId not stable on hydration with mid-render state update (React 18) #31653

Open
kognise opened this issue Dec 2, 2024 · 1 comment
Open
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug

Comments

@kognise
Copy link

kognise commented Dec 2, 2024

React version: 18.3.1, 18.0.0

Does not occur in React 19, but we can't use React 19.

Summary

I am fully expecting this to be programmer error, but this behavior deeply puzzles me and I can't find any documented reason for it. If this isn't a bug in React, I would definitely consider it a bug in React documentation :)

As far as I can tell, this code follows all of the rules of hooks and documented invariants:

function App() {
  const _id = useId() // If commented out, no warning.

  const [prevValue, setPrevValue] = useState(false)
  if (prevValue === false) setPrevValue(true) // If commented out, no warning.

  return <Inner />
}

// If this component's body is copied into `App`, no warning.
function Inner() {
  const id = useId() // <---- NOT STABLE!

  return <div id={id} />
}

However, it fails with a hydration mismatch error:

client.js:2427 Warning: Prop `id` did not match. Server: ":R6:" Client: ":R2:" Error Component Stack
    at div (<anonymous>)
    at Inner (client.js:23592:40)
    at App (client.js:23596:41)
    at body (<anonymous>)
    at html (<anonymous>)
    at Html (<anonymous>)

Steps To Reproduce

I created a GitHub repo with a minimal reproduction. Steps to run are in the README: https://github.com/kognise/react-reproduction

Alternately, you should be able to see the same behavior by copying the top code sample into any server-rendered (and hydrated) React app.

The current behavior

React prints the warning Prop `id` did not match. Server: ":R6:" Client: ":R2:".

The expected behavior

I would expect this to just work with no issues.

Modifying the snippet as commented makes the warning go away.

Thanks!

@kognise kognise added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Dec 2, 2024
@kognise
Copy link
Author

kognise commented Dec 4, 2024

Okay, looks like this was fixed by #25713, but wasn't backported to React 18. Could we get a backport? I am looking into creating a PR myself now.

kognise added a commit to kognise/react-fork that referenced this issue Dec 4, 2024
A hydration error occurs when using `useId` with a parent that has a render phase update. This has already been fixed in React 19 by facebook#25713.

React 18 will have users for some time, and this issue is showing up in production. Therefore, this backports that fix to React 18.

Fixes facebook#31653.
kognise added a commit to kognise/react-fork that referenced this issue Dec 4, 2024
A hydration error occurs when using `useId` with a parent that has a render phase update. This has already been fixed in React 19 by facebook#25713.

React 18 will have users for some time, and this issue is showing up in production. Therefore, this backports that fix to React 18.

Fixes facebook#31653.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug
Projects
None yet
Development

No branches or pull requests

1 participant