Skip to content

fix(react): merge className with runtime-managed host classes#827

Open
ShaneK wants to merge 4 commits into
mainfrom
FW-7601
Open

fix(react): merge className with runtime-managed host classes#827
ShaneK wants to merge 4 commits into
mainfrom
FW-7601

Conversation

@ShaneK

@ShaneK ShaneK commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Resolves #485

Pull request checklist

Please check if your PR fulfills the following requirements:

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)
  • Build (npm run build) was run locally for affected output targets
  • Tests (npm test) were run locally and passed
  • Prettier (npm run prettier) was run locally and passed

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

@lit/react maps React's className prop to the host's class attribute and rewrites it wholesale on every render. That wipes the classes the Stencil runtime manages on the host: hydrated, sc-* scope classes, mode classes, and state classes like interactive. So when an app drives className (for example a form library setting Ionic's ion-invalid / ion-touched validation classes), those app classes replace the runtime's classes instead of coexisting with them, and the component loses styling and hydration state.

Issue URL:

What is the new behavior?

createComponent now wraps the @lit/react component and withholds className/class so React never writes the class attribute directly. It reconciles the app's class value against the live host in a layout effect using a new mergeClassNames helper. The merge keeps runtime-managed classes the app never set, appends new app classes, and removes only the app classes that were dropped since the previous render (tracked with a previousClassName ref). It uses an isomorphic layout effect so it falls back to useEffect during server rendering and doesn't warn.

Does this introduce a breaking change?

  • Yes
  • No

Other information

@ShaneK ShaneK requested a review from a team as a code owner July 1, 2026 21:28

@OS-jacobbell OS-jacobbell left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confirmed this fixes the issue and passes Ionic Framework's e2e tests.

@ShaneK

ShaneK commented Jul 10, 2026

Copy link
Copy Markdown
Contributor Author

@johnjenkins Would you have some time to review this one? Just for verification that it all makes sense

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: React output target v0.7.0 overwrites classNames

2 participants