@@ -6,7 +6,10 @@ interface LooseShadowRoot extends ShadowRoot {
6
6
}
7
7
8
8
// See https://github.com/facebook/react/issues/9242#issuecomment-543117675
9
- function retargetReactEvents ( container : Node , shadow : LooseShadowRoot ) : void {
9
+ function retargetReactEvents (
10
+ container : Node ,
11
+ shadow : LooseShadowRoot ,
12
+ ) : ( ) => void {
10
13
Object . defineProperty ( container , 'ownerDocument' , { value : shadow } ) ;
11
14
/* eslint-disable no-param-reassign */
12
15
shadow . defaultView = window ;
@@ -20,7 +23,7 @@ function retargetReactEvents(container: Node, shadow: LooseShadowRoot): void {
20
23
options : ElementCreationOptions ,
21
24
) : Element => document . createElementNS ( ns , tagName , options ) ;
22
25
shadow . createTextNode = ( text : string ) : Text => document . createTextNode ( text ) ;
23
- forceRetarget ( shadow ) ;
26
+ return forceRetarget ( shadow ) ;
24
27
/* eslint-enable no-param-reassign */
25
28
}
26
29
@@ -31,34 +34,48 @@ class ReactHTMLElement extends HTMLElement {
31
34
32
35
private mountSelector : string ;
33
36
37
+ private retargetCleanupFunction : ( ) => void ;
38
+
34
39
get mountPoint ( ) : Element {
35
40
if ( this . _mountPoint ) return this . _mountPoint ;
36
41
37
42
const shadow = this . attachShadow ( { mode : 'open' } ) ;
38
43
shadow . innerHTML = this . template ;
39
44
this . _mountPoint = shadow . querySelector ( this . mountSelector ) as Element ;
40
45
41
- retargetReactEvents ( this . _mountPoint , shadow ) ;
46
+ this . retargetCleanup = retargetReactEvents ( this . _mountPoint , shadow ) ;
42
47
43
48
return this . _mountPoint ;
44
49
}
45
50
46
51
set mountPoint ( mount : Element ) {
47
52
this . _mountPoint = mount ;
48
53
if ( this . shadowRoot ) {
49
- retargetReactEvents ( mount , this . shadowRoot ) ;
54
+ this . retargetCleanup = retargetReactEvents ( mount , this . shadowRoot ) ;
50
55
}
51
56
}
52
57
58
+ get retargetCleanup ( ) : ( ) => void {
59
+ return this . retargetCleanupFunction ;
60
+ }
61
+
62
+ set retargetCleanup ( cleanupFunction : ( ) => void ) {
63
+ // Ensure that we cleanup an old listeners before we forget the cleanup function.
64
+ this . retargetCleanup ( ) ;
65
+ this . retargetCleanupFunction = cleanupFunction ;
66
+ }
67
+
53
68
disconnectedCallback ( ) : void {
54
69
if ( ! this . _mountPoint ) return ;
70
+ this . retargetCleanup ( ) ;
55
71
ReactDOM . unmountComponentAtNode ( this . _mountPoint ) ;
56
72
}
57
73
58
74
constructor ( template = '<div></div>' , mountSelector = 'div' ) {
59
75
super ( ) ;
60
76
this . template = template ;
61
77
this . mountSelector = mountSelector ;
78
+ this . retargetCleanupFunction = ( ) => { } ;
62
79
}
63
80
}
64
81
0 commit comments