55import type { ProviderFnParams } from '../../types' ;
66import { createBaseBridgeComponent } from './bridge-base' ;
77import ReactDOM from 'react-dom' ;
8+ import React from 'react' ;
89
910export interface CreateRootOptions {
1011 identifierPrefix ?: string ;
@@ -28,40 +29,54 @@ export interface Root {
2829export function createReact16Or17Root (
2930 container : Element | DocumentFragment ,
3031) : Root {
31- return {
32- render ( children : React . ReactNode ) {
33- /**
34- * Detect React version
35- */
36- const reactVersion = ReactDOM . version || '' ;
37- const isReact18 = reactVersion . startsWith ( '18' ) ;
38- const isReact19 = reactVersion . startsWith ( '19' ) ;
32+ /**
33+ * Detect React version
34+ */
35+ const reactVersion = ReactDOM . version || '' ;
36+ const isReact18Plus =
37+ reactVersion . startsWith ( '18' ) || reactVersion . startsWith ( '19' ) ;
3938
40- /**
41- * Throw error for React 19 (skip in test environment)
42- *
43- * Note: Due to Module Federation sharing mechanism, the actual version detected here
44- * might be 18 or 19, even if the application itself uses React 16/17.
45- * This happens because in MF environments, different remote modules may share different React versions.
46- * The console may throw warnings about version and API mismatches. If you need to resolve these issues,
47- * consider disabling the shared configuration for React.
48- */
49- if ( isReact19 && process . env . NODE_ENV !== 'test' ) {
50- throw new Error (
51- `React 19 detected in legacy mode. This is not supported. ` +
52- `Please use the version-specific import: ` +
53- `import { createBridgeComponent } from '@module-federation/bridge-react/v19'` ,
54- ) ;
55- }
39+ if ( isReact18Plus ) {
40+ // For React 18+, use the modern createRoot API
41+ let modernRoot : any = null ;
42+
43+ return {
44+ render ( children : React . ReactNode ) {
45+ if ( ! modernRoot ) {
46+ try {
47+ // Import createRoot dynamically to avoid issues if not available
48+ const { createRoot } = require ( 'react-dom/client' ) ;
49+ modernRoot = createRoot ( container ) ;
50+ } catch ( error ) {
51+ // Fallback to legacy API if createRoot is not available
52+ // @ts -ignore - React 17's render method is deprecated but still functional
53+ ReactDOM . render ( children , container ) ;
54+ return ;
55+ }
56+ }
57+ modernRoot . render ( children ) ;
58+ } ,
59+ unmount ( ) {
60+ if ( modernRoot ) {
61+ modernRoot . unmount ( ) ;
62+ } else {
63+ ReactDOM . unmountComponentAtNode ( container as Element ) ;
64+ }
65+ } ,
66+ } ;
67+ }
5668
69+ // For React 16/17, use the legacy API
70+ return {
71+ render ( children : React . ReactNode ) {
5772 /**
58- * Provide warning for React 18
73+ * Provide warning for non-test environments to suggest version-specific imports
5974 */
60- if ( isReact18 ) {
75+ if ( process . env . NODE_ENV !== 'test' ) {
6176 console . warn (
62- `[Bridge-React] React 18 detected in legacy mode . ` +
63- `For better compatibility, please use the version-specific import : ` +
64- `import { createBridgeComponent } from '@module-federation/bridge-react/v18'` ,
77+ `[Bridge-React] React 16/17 detected. ` +
78+ `For better compatibility, consider using version-specific imports : ` +
79+ `import { createBridgeComponent } from '@module-federation/bridge-react/v18' or v19 ` ,
6580 ) ;
6681 }
6782
0 commit comments