1
- import { useLayoutEffect , useRef , useState } from 'react' ;
2
1
import * as React from 'react' ;
3
2
import ReactDOM from 'react-dom' ;
4
- import ReactDOMClient from 'react-dom/client' ;
5
3
import type {
6
4
ProviderParams ,
7
5
RenderFnParams ,
8
6
} from '@module-federation/bridge-shared' ;
9
7
import { ErrorBoundary } from 'react-error-boundary' ;
10
8
import { RouterContext } from './context' ;
11
- import { LoggerInstance , atLeastReact18 } from './utils' ;
9
+ import { LoggerInstance } from './utils' ;
12
10
import { federationRuntime } from './plugin' ;
11
+ import { createRoot } from './compat' ;
13
12
14
13
type RenderParams = RenderFnParams & {
15
14
[ key : string ] : unknown ;
@@ -18,7 +17,7 @@ type DestroyParams = {
18
17
moduleName : string ;
19
18
dom : HTMLElement ;
20
19
} ;
21
- type RootType = HTMLElement | ReactDOMClient . Root ;
20
+ type RootType = HTMLElement | ReturnType < typeof createRoot > ;
22
21
23
22
export type ProviderFnParams < T > = {
24
23
rootComponent : React . ComponentType < T > ;
@@ -67,7 +66,6 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
67
66
instance ?. bridgeHook ?. lifecycle ?. beforeBridgeRender ?. emit ( info ) || { } ;
68
67
69
68
const rootComponentWithErrorBoundary = (
70
- // set ErrorBoundary for RawComponent rendering error, usually caused by user app rendering error
71
69
< ErrorBoundary FallbackComponent = { fallback } >
72
70
< RawComponent
73
71
appInfo = { {
@@ -81,53 +79,34 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
81
79
/>
82
80
</ ErrorBoundary >
83
81
) ;
84
- // call render function
85
- if ( atLeastReact18 ( React ) ) {
86
- if ( bridgeInfo ?. render ) {
87
- // in case bridgeInfo?.render is an async function, resolve this to promise
88
- Promise . resolve (
89
- bridgeInfo ?. render ( rootComponentWithErrorBoundary , dom ) ,
90
- ) . then ( ( root : RootType ) => rootMap . set ( info . dom , root ) ) ;
91
- } else {
92
- const root : RootType = ReactDOMClient . createRoot ( info . dom ) ;
93
- root . render ( rootComponentWithErrorBoundary ) ;
94
- rootMap . set ( info . dom , root ) ;
95
- }
82
+
83
+ if ( bridgeInfo ?. render ) {
84
+ // in case bridgeInfo?.render is an async function, resolve this to promise
85
+ Promise . resolve (
86
+ bridgeInfo ?. render ( rootComponentWithErrorBoundary , dom ) ,
87
+ ) . then ( ( root : RootType ) => rootMap . set ( info . dom , root ) ) ;
96
88
} else {
97
- // react 17 render
98
- const renderFn = bridgeInfo ? .render || ReactDOM . render ;
99
- renderFn ?. ( rootComponentWithErrorBoundary , info . dom ) ;
89
+ const root = createRoot ( info . dom ) ;
90
+ root . render ( rootComponentWithErrorBoundary ) ;
91
+ rootMap . set ( info . dom , root ) ;
100
92
}
93
+
101
94
instance ?. bridgeHook ?. lifecycle ?. afterBridgeRender ?. emit ( info ) || { } ;
102
95
} ,
103
96
104
- async destroy ( info : DestroyParams ) {
105
- LoggerInstance . debug ( `createBridgeComponent destroy Info` , {
106
- dom : info . dom ,
107
- } ) ;
108
- instance ?. bridgeHook ?. lifecycle ?. beforeBridgeDestroy ?. emit ( info ) ;
109
-
110
- // call destroy function
111
- if ( atLeastReact18 ( React ) ) {
112
- const root = rootMap . get ( info . dom ) ;
113
- ( root as ReactDOMClient . Root ) ?. unmount ( ) ;
97
+ destroy ( info : DestroyParams ) {
98
+ LoggerInstance . debug ( `createBridgeComponent destroy Info` , info ) ;
99
+ const root = rootMap . get ( info . dom ) ;
100
+ if ( root ) {
101
+ if ( 'unmount' in root ) {
102
+ root . unmount ( ) ;
103
+ } else {
104
+ ReactDOM . unmountComponentAtNode ( root as HTMLElement ) ;
105
+ }
114
106
rootMap . delete ( info . dom ) ;
115
- } else {
116
- ReactDOM . unmountComponentAtNode ( info . dom ) ;
117
107
}
118
-
119
- instance ?. bridgeHook ?. lifecycle ?. afterBridgeDestroy ?. emit ( info ) ;
108
+ instance ?. bridgeHook ?. lifecycle ?. destroyBridge ?. emit ( info ) ;
120
109
} ,
121
- rawComponent : bridgeInfo . rootComponent ,
122
- __BRIDGE_FN__ : ( _args : T ) => { } ,
123
110
} ;
124
111
} ;
125
112
}
126
-
127
- export function ShadowRoot ( info : { children : ( ) => JSX . Element } ) {
128
- const [ root ] = useState ( null ) ;
129
- const domRef = useRef ( null ) ;
130
- useLayoutEffect ( ( ) => { } ) ;
131
-
132
- return < div ref = { domRef } > { root && < info . children /> } </ div > ;
133
- }
0 commit comments