Skip to content

fix(react): Fix hydration mismatch for experimentalReactChildren#15146

Open
kedarvartak wants to merge 2 commits intowithastro:mainfrom
kedarvartak:fix/react-children-client-props
Open

fix(react): Fix hydration mismatch for experimentalReactChildren#15146
kedarvartak wants to merge 2 commits intowithastro:mainfrom
kedarvartak:fix/react-children-client-props

Conversation

@kedarvartak
Copy link
Contributor

Fixes hydration mismatch when using experimentalReactChildren option.

Problem

When experimentalReactChildren=true, children passed to React components had inconsistent prop handling between server and client:

  • Server correctly mapped class to className and generated unique key props
  • Client read DOM attributes directly without applying the same transformations

This caused React warnings and hydration errors:

  • "Invalid DOM property 'class'. Did you mean 'className'?"
  • "Each child in a list should have a unique 'key' prop."

Solution

Updated the client-side createReactElementFromDOMElement function in client.ts to:

  • Map DOM attribute names to React prop names (class to className, for to htmlFor)
  • Generate unique key props for each child element

Testing

Added unit tests for class-to-className mapping and key generation. All existing tests pass.

Closes #15102

@changeset-bot
Copy link

changeset-bot bot commented Jan 8, 2026

⚠️ No Changeset found

Latest commit: afa562b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added pkg: react Related to React (scope) pkg: integration Related to any renderer integration (scope) labels Jan 8, 2026
@matthewp
Copy link
Contributor

Can you change this to go against next instead?

return c.data;
} else if (c.nodeType === Node.ELEMENT_NODE) {
return createReactElementFromDOMElement(c);
return createReactElementFromDOMElement(c, id, childKey++);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, please avoid post update expressions like this, because they are very easy to get wrong. Instead, let's do this

Suggested change
return createReactElementFromDOMElement(c, id, childKey++);
childKey += 1;
return createReactElementFromDOMElement(c, id, childKey);


function createReactElementFromDOMElement(element: any, id?: number, key?: number): any {
if (id === undefined) {
id = clientIds++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Suggested change
id = clientIds++;
clientIds += 1;
id = clientIds;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: integration Related to any renderer integration (scope) pkg: react Related to React (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

experimentalReactChildren flag doesn't map node.class and children keys on client

3 participants