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: Can't hydrate useOpaqueIdentifier generated object in another component #20127

Closed
diegohaz opened this issue Oct 29, 2020 · 3 comments
Closed

Comments

@diegohaz
Copy link

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

  1. Create a simple server rendered app (for example, using Next.js).
  2. Create a component that uses React.unstable_useOpaqueIdentifier and passes the generated object to a component up in the tree through callbacks.
  3. Try to render the generated ID to a prop in the ancestor component.

Link to code example:

https://codesandbox.io/s/react-useopaqueidentifier-aria-activedescendant-bug-geutb?file=/pages/index.js:0-412

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:

// 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

@diegohaz diegohaz added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Oct 29, 2020
@eps1lon eps1lon added Component: DOM Type: Needs Investigation and removed Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels Oct 29, 2020
@eps1lon
Copy link
Collaborator

eps1lon commented Oct 29, 2020

Repro without nextjs: https://codesandbox.io/s/beautiful-browser-2kkxy?file=/src/index.js

@diegohaz
Copy link
Author

I was able to find a workaround for this. Instead of passing the ID object around, we can pass the element ref and get its ID from the DOM: https://codesandbox.io/s/blissful-microservice-m1vvd?file=/src/index.js

I guess this workaround can also be used for ID lists.

I wonder if it's technically possible to improve the useOpaqueIdentifier hook so it works similarly to element refs. That is, their value should be accessible within effects and event callbacks after they're rendered to the DOM.

@eps1lon
Copy link
Collaborator

eps1lon commented Nov 23, 2021

Fixed when using useId which replace useOpaqueIdentifier: https://codesandbox.io/s/react-useopaqueidentifier-aria-activedescendant-bug-forked-wg9df?file=/pages/index.js

@eps1lon eps1lon closed this as completed Nov 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants