@@ -64,17 +64,18 @@ export default function r2wc<Props, Context>(
6464 }
6565
6666 class ReactWebComponent extends HTMLElement {
67- static get observedAttributes ( ) {
68- return Object . keys ( mapAttributeProp ) ;
69- }
70-
71- private connected = true ;
67+ private connected = false ;
7268 private context ?: Context ;
7369 props : Props = { } as Props ;
7470 container : HTMLElement ;
71+ observer : MutationObserver ;
7572
7673 constructor ( ) {
7774 super ( ) ;
75+ this . observer = new MutationObserver ( ( mutations ) =>
76+ this . attributesChanged ( mutations )
77+ ) ;
78+ this . observer . observe ( this , { attributes : true } ) ;
7879
7980 if ( options . shadow ) {
8081 this . container = this . attachShadow ( {
@@ -90,27 +91,26 @@ export default function r2wc<Props, Context>(
9091
9192 connectedCallback ( ) {
9293 this . connected = true ;
93- this . render ( ) ;
9494
9595 for ( const prop of propNames ) {
9696 this . setProps ( prop ) ;
9797 }
9898
99- this . update ( ) ;
99+ this . mount ( ) ;
100100 }
101101
102102 disconnectedCallback ( ) {
103103 this . connected = false ;
104104
105- if ( this . context ) {
106- renderer . unmount ( this . context ) ;
107- }
105+ this . unmount ( ) ;
108106 }
109107
110- attributeChangedCallback ( attribute : Extract < keyof Props , string > ) {
111- this . setProps ( attribute ) ;
108+ private attributesChanged ( mutations : MutationRecord [ ] ) {
109+ mutations . forEach ( ( { attributeName } ) => {
110+ this . setProps ( attributeName as Extract < keyof Props , string > ) ;
111+ } ) ;
112112
113- this . render ( ) ;
113+ this . update ( ) ;
114114 }
115115
116116 private setProps ( prop : Extract < keyof Props , string > ) {
@@ -125,33 +125,32 @@ export default function r2wc<Props, Context>(
125125 const value = reactProps [ prop ] ?? this . getAttribute ( attribute ) ;
126126 const type = propTypes [ prop ] ;
127127 const transform = transforms [ type ] ;
128- if ( reactProps [ prop ] ) {
128+ if ( prop in reactProps ) {
129129 this . props [ prop ] = value ;
130130 } else if ( value && transform ?. parse ) {
131131 //@ts -ignore
132132 this . props [ prop ] = transform . parse ( value , this ) ;
133133 }
134134 }
135135
136- private render ( ) {
137- if ( ! this . connected ) return ;
138-
139- if ( ! this . context ) {
140- this . mount ( ) ;
141- } else {
142- this . update ( ) ;
143- }
144- }
145-
146136 private update ( ) {
137+ if ( ! this . connected ) return ;
147138 if ( ! this . context ) return ;
148139
149140 renderer . update ( this . context , this . props ) ;
150141 }
151142
152143 private mount ( ) {
144+ if ( ! this . connected ) throw new Error ( `${ ReactComponent } is not in a DOM` ) ;
145+ if ( this . context ) throw new Error ( `${ ReactComponent } is already mounted` ) ;
146+
153147 this . context = renderer . mount ( this . container , ReactComponent , this . props ) ;
154148 }
149+
150+ private unmount ( ) {
151+ if ( ! this . context ) return ;
152+ renderer . unmount ( this . context ) ;
153+ }
155154 }
156155
157156 return ReactWebComponent ;
0 commit comments