Skip to content

Fix: React 19 compatibility - move react, react-dom, and react-transition-group to peerDependencies#2743

Open
ankita10119 wants to merge 1 commit intomasterfrom
SDK-8307
Open

Fix: React 19 compatibility - move react, react-dom, and react-transition-group to peerDependencies#2743
ankita10119 wants to merge 1 commit intomasterfrom
SDK-8307

Conversation

@ankita10119
Copy link
Contributor

Changes

Problem

Users running auth0-lock in a React 19 project encounter the following error immediately on lock.show(), preventing the Lock widget from rendering:

Uncaught Error: Objects are not valid as a React child

Reported in: #2739

Root Cause

react, react-dom, and react-transition-group were declared as regular dependencies in package.json. This caused npm to install Lock's own copy of React 18.3.1 inside auth0-lock/node_modules, separate from the consuming app's React version.

In Vite-based projects (and similar bundlers that don't deduplicate modules across symlinked packages), this results in two React instances existing simultaneously:

  • Lock creates React elements using its bundled React 18.3.1
  • react-transition-group resolves to the app's React 19 (via Vite's module deduplication)
  • React 19's mapIntoArray (inside React.Children.map) receives elements created by React 18, elements with a different internal structure (ref as a top-level key in React 18 vs inside props in React 19)
  • React 19 does not recognise these as valid React elements → throws

This is the classic "multiple React instances" problem. The fix is to declare React as a peerDependency so Lock always uses the consuming app's React instance.

Fix

Moved react, react-dom, and react-transition-group from dependencies to peerDependencies:

"peerDependencies": {
   "react": ">=16.8.0",
   "react-dom": ">=16.8.0",
   "react-transition-group": ">=4.4.5"
 }

Added them to devDependencies so the local build, tests, and development workflow continue to work unchanged.

This is the standard pattern for React component libraries, React should never be bundled as a private dependency.

References

Closes #2739

Testing

  • Reproduced the error using auth0-lock@14.2.4 (published) + React 19.2.4 in a Vite app, Objects are not valid as a React child error appeared immediately on lock.show()
  • Applied fix, packed the local build as a tarball (npm pack), installed it in the same Vite app
  • Verified the React 19 error is completely gone, Lock widget renders, login flow works end to end
  • Confirmed no regression on React 18 setup
  • This change adds unit test coverage
  • This change adds integration test coverage
  • This change has been tested on the latest version of the platform/language

Concerns & Answers

Q: Will this break users who use Lock via CDN / standalone bundle?

No. The CDN build (lock.min.js) is a self-contained webpack bundle that includes all dependencies bundled into a single file. peerDependencies only affect npm package consumers and have no impact on the CDN bundle.


Q: Will this break users using Lock via npm in a non-React project (vanilla JS, Vue, Angular, etc.)?

These users will now need to explicitly install react, react-dom, and react-transition-group as dependencies in their own project. Before this fix, these were being installed silently as transitive dependencies. Lock has always been a React-based widget internally, React was always required at runtime. The change makes this requirement explicit rather than hidden. npm will warn users about missing peerDependencies if they haven't installed them.

For non-React projects, using Lock via the CDN bundle is the simpler option and remains unaffected.


Q: Does this affect React 16, 17, or 18 users?

No. The peerDependencies range is >=16.8.0, so all supported React versions continue to work. The only change is that Lock no longer silently installs its own private React copy, it uses whichever version the consuming app has installed.


Q: Why was react-transition-group also moved to peerDependencies?

react-transition-group itself has react and react-dom as peerDependencies. If it resolves to a different React instance than the one Lock is using, the same mismatch problem can occur.
Moving it to peerDependencies ensures it always uses the same React instance as the consuming app and Lock.

Checklist

@ankita10119 ankita10119 requested a review from a team as a code owner March 18, 2026 10:40
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.

Auth0-lock 14.2.4 Is not compatible with the React and React-dom 19.2.4

2 participants