-
Notifications
You must be signed in to change notification settings - Fork 49.1k
Closed
Labels
Description
React version: experimental
I found this bug while trying out useOpaqueIdentifier
on a component that uses aria-activedescendant
. It works great on a CRA app, but it breaks on server rendered apps.
The way it's implemented is that each item registers its id into a state up in the tree so the container element can get the active id and render it on the aria-activedescendant
prop.
Steps To Reproduce
- Create a simple server rendered app (for example, using Next.js).
- Create a component that uses
React.unstable_useOpaqueIdentifier
and passes the generated object to a component up in the tree through callbacks. - Try to render the generated ID to a prop in the ancestor component.
Link to code example:
The current behavior
It throws an error:
Unhandled Runtime Error
Error: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.
Call Stack
Object.readValue
node_modules/react-dom/cjs/react-dom.development.js (16555:0)
diffProperties
node_modules/react-dom/cjs/react-dom.development.js (9475:0)
prepareUpdate
node_modules/react-dom/cjs/react-dom.development.js (10352:0)
updateHostComponent$1
node_modules/react-dom/cjs/react-dom.development.js (20070:0)
completeWork
node_modules/react-dom/cjs/react-dom.development.js (20236:0)
completeUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js (23738:0)
performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js (23710:0)
workLoopSync
node_modules/react-dom/cjs/react-dom.development.js (23618:0)
renderRootSync
node_modules/react-dom/cjs/react-dom.development.js (23577:0)
performConcurrentWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js (22968:0)
workLoop
node_modules/scheduler/cjs/scheduler.development.js (590:0)
flushWork
node_modules/scheduler/cjs/scheduler.development.js (545:0)
MessagePort.performWorkUntilDeadline
node_modules/scheduler/cjs/scheduler.development.js (157:0)
I believe it's triggered here:
react/packages/react-dom/src/client/ReactDOMComponent.js
Lines 786 to 789 in 993ca53
// If we encounter useOpaqueReference's opaque object, this means we are hydrating. | |
// In this case, call the opaque object's toString function which generates a new client | |
// ID so client and server IDs match and throws to rerender. | |
nextProp.toString(); |
The expected behavior
It works well when not using SSR:
https://codesandbox.io/s/react-useopaqueidentifier-aria-activedescendant-y3f22
akinncar, tujoworker and eps1lon