@@ -18,6 +18,12 @@ describe('ReactDOMFiber', () => {
1818
1919  beforeEach ( ( )  =>  { 
2020    container  =  document . createElement ( 'div' ) ; 
21+     document . body . appendChild ( container ) ; 
22+   } ) ; 
23+ 
24+   afterEach ( ( )  =>  { 
25+     document . body . removeChild ( container ) ; 
26+     container  =  null ; 
2127  } ) ; 
2228
2329  it ( 'should render strings as children' ,  ( )  =>  { 
@@ -205,12 +211,12 @@ describe('ReactDOMFiber', () => {
205211  } ; 
206212
207213  const  assertNamespacesMatch  =  function ( tree )  { 
208-     container  =  document . createElement ( 'div' ) ; 
214+     let   testContainer  =  document . createElement ( 'div' ) ; 
209215    svgEls  =  [ ] ; 
210216    htmlEls  =  [ ] ; 
211217    mathEls  =  [ ] ; 
212218
213-     ReactDOM . render ( tree ,  container ) ; 
219+     ReactDOM . render ( tree ,  testContainer ) ; 
214220    svgEls . forEach ( el  =>  { 
215221      expect ( el . namespaceURI ) . toBe ( 'http://www.w3.org/2000/svg' ) ; 
216222    } ) ; 
@@ -221,8 +227,8 @@ describe('ReactDOMFiber', () => {
221227      expect ( el . namespaceURI ) . toBe ( 'http://www.w3.org/1998/Math/MathML' ) ; 
222228    } ) ; 
223229
224-     ReactDOM . unmountComponentAtNode ( container ) ; 
225-     expect ( container . innerHTML ) . toBe ( '' ) ; 
230+     ReactDOM . unmountComponentAtNode ( testContainer ) ; 
231+     expect ( testContainer . innerHTML ) . toBe ( '' ) ; 
226232  } ; 
227233
228234  it ( 'should render one portal' ,  ( )  =>  { 
@@ -874,7 +880,6 @@ describe('ReactDOMFiber', () => {
874880
875881  it ( 'should not onMouseLeave when staying in the portal' ,  ( )  =>  { 
876882    const  portalContainer  =  document . createElement ( 'div' ) ; 
877-     document . body . appendChild ( container ) ; 
878883    document . body . appendChild ( portalContainer ) ; 
879884
880885    let  ops  =  [ ] ; 
@@ -944,7 +949,6 @@ describe('ReactDOMFiber', () => {
944949        'leave parent' ,  // Only when we leave the portal does onMouseLeave fire. 
945950      ] ) ; 
946951    }  finally  { 
947-       document . body . removeChild ( container ) ; 
948952      document . body . removeChild ( portalContainer ) ; 
949953    } 
950954  } ) ; 
@@ -987,82 +991,77 @@ describe('ReactDOMFiber', () => {
987991  } ) ; 
988992
989993  it ( 'should not update event handlers until commit' ,  ( )  =>  { 
990-     document . body . appendChild ( container ) ; 
991-     try  { 
992-       let  ops  =  [ ] ; 
993-       const  handlerA  =  ( )  =>  ops . push ( 'A' ) ; 
994-       const  handlerB  =  ( )  =>  ops . push ( 'B' ) ; 
995- 
996-       class  Example  extends  React . Component  { 
997-         state  =  { flip : false ,  count : 0 } ; 
998-         flip ( )  { 
999-           this . setState ( { flip : true ,  count : this . state . count  +  1 } ) ; 
1000-         } 
1001-         tick ( )  { 
1002-           this . setState ( { count : this . state . count  +  1 } ) ; 
1003-         } 
1004-         render ( )  { 
1005-           const  useB  =  ! this . props . forceA  &&  this . state . flip ; 
1006-           return  < div  onClick = { useB  ? handlerB  : handlerA }  /> ; 
1007-         } 
994+     let  ops  =  [ ] ; 
995+     const  handlerA  =  ( )  =>  ops . push ( 'A' ) ; 
996+     const  handlerB  =  ( )  =>  ops . push ( 'B' ) ; 
997+ 
998+     class  Example  extends  React . Component  { 
999+       state  =  { flip : false ,  count : 0 } ; 
1000+       flip ( )  { 
1001+         this . setState ( { flip : true ,  count : this . state . count  +  1 } ) ; 
10081002      } 
1003+       tick ( )  { 
1004+         this . setState ( { count : this . state . count  +  1 } ) ; 
1005+       } 
1006+       render ( )  { 
1007+         const  useB  =  ! this . props . forceA  &&  this . state . flip ; 
1008+         return  < div  onClick = { useB  ? handlerB  : handlerA }  /> ; 
1009+       } 
1010+     } 
10091011
1010-       class  Click  extends  React . Component  { 
1011-         constructor ( )  { 
1012-           super ( ) ; 
1013-           node . click ( ) ; 
1014-         } 
1015-         render ( )  { 
1016-           return  null ; 
1017-         } 
1012+     class  Click  extends  React . Component  { 
1013+       constructor ( )  { 
1014+         super ( ) ; 
1015+         node . click ( ) ; 
10181016      } 
1017+       render ( )  { 
1018+         return  null ; 
1019+       } 
1020+     } 
10191021
1020-        let  inst ; 
1021-        ReactDOM . render ( [ < Example  key = "a"  ref = { n  =>  ( inst  =  n ) }  /> ] ,  container ) ; 
1022-        const  node  =  container . firstChild ; 
1023-        expect ( node . tagName ) . toEqual ( 'DIV' ) ; 
1022+     let  inst ; 
1023+     ReactDOM . render ( [ < Example  key = "a"  ref = { n  =>  ( inst  =  n ) }  /> ] ,  container ) ; 
1024+     const  node  =  container . firstChild ; 
1025+     expect ( node . tagName ) . toEqual ( 'DIV' ) ; 
10241026
1025-        node . click ( ) ; 
1027+     node . click ( ) ; 
10261028
1027-        expect ( ops ) . toEqual ( [ 'A' ] ) ; 
1028-        ops  =  [ ] ; 
1029+     expect ( ops ) . toEqual ( [ 'A' ] ) ; 
1030+     ops  =  [ ] ; 
10291031
1030-        // Render with the other event handler. 
1031-        inst . flip ( ) ; 
1032+     // Render with the other event handler. 
1033+     inst . flip ( ) ; 
10321034
1033-        node . click ( ) ; 
1035+     node . click ( ) ; 
10341036
1035-        expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1036-        ops  =  [ ] ; 
1037+     expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1038+     ops  =  [ ] ; 
10371039
1038-        // Rerender without changing any props. 
1039-        inst . tick ( ) ; 
1040+     // Rerender without changing any props. 
1041+     inst . tick ( ) ; 
10401042
1041-        node . click ( ) ; 
1043+     node . click ( ) ; 
10421044
1043-        expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1044-        ops  =  [ ] ; 
1045+     expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1046+     ops  =  [ ] ; 
10451047
1046-        // Render a flip back to the A handler. The second component invokes the 
1047-        // click handler during render to simulate a click during an aborted 
1048-        // render. I use this hack because at current time we don't have a way to 
1049-        // test aborted ReactDOM renders. 
1050-        ReactDOM . render ( 
1051-          [ < Example  key = "a"  forceA = { true }  /> ,  < Click  key = "b"  /> ] , 
1052-          container , 
1053-        ) ; 
1048+     // Render a flip back to the A handler. The second component invokes the 
1049+     // click handler during render to simulate a click during an aborted 
1050+     // render. I use this hack because at current time we don't have a way to 
1051+     // test aborted ReactDOM renders. 
1052+     ReactDOM . render ( 
1053+       [ < Example  key = "a"  forceA = { true }  /> ,  < Click  key = "b"  /> ] , 
1054+       container , 
1055+     ) ; 
10541056
1055-        // Because the new click handler has not yet committed, we should still 
1056-        // invoke B. 
1057-        expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1058-        ops  =  [ ] ; 
1057+     // Because the new click handler has not yet committed, we should still 
1058+     // invoke B. 
1059+     expect ( ops ) . toEqual ( [ 'B' ] ) ; 
1060+     ops  =  [ ] ; 
10591061
1060-       // Any click that happens after commit, should invoke A. 
1061-       node . click ( ) ; 
1062-       expect ( ops ) . toEqual ( [ 'A' ] ) ; 
1063-     }  finally  { 
1064-       document . body . removeChild ( container ) ; 
1065-     } 
1062+     // Any click that happens after commit, should invoke A. 
1063+     node . click ( ) ; 
1064+     expect ( ops ) . toEqual ( [ 'A' ] ) ; 
10661065  } ) ; 
10671066
10681067  it ( 'should not crash encountering low-priority tree' ,  ( )  =>  { 
@@ -1178,4 +1177,63 @@ describe('ReactDOMFiber', () => {
11781177    container . appendChild ( fragment ) ; 
11791178    expect ( container . innerHTML ) . toBe ( '<div>foo</div>' ) ; 
11801179  } ) ; 
1180+ 
1181+   // Regression test for https://github.com/facebook/react/issues/12643#issuecomment-413727104 
1182+   it ( 'should not diff memoized host components' ,  ( )  =>  { 
1183+     let  inputRef  =  React . createRef ( ) ; 
1184+     let  didCallOnChange  =  false ; 
1185+ 
1186+     class  Child  extends  React . Component  { 
1187+       state  =  { } ; 
1188+       componentDidMount ( )  { 
1189+         document . addEventListener ( 'click' ,  this . update ,  true ) ; 
1190+       } 
1191+       componentWillUnmount ( )  { 
1192+         document . removeEventListener ( 'click' ,  this . update ,  true ) ; 
1193+       } 
1194+       update  =  ( )  =>  { 
1195+         // We're testing that this setState() 
1196+         // doesn't cause React to commit updates 
1197+         // to the input outside (which would itself 
1198+         // prevent the parent's onChange parent handler 
1199+         // from firing). 
1200+         this . setState ( { } ) ; 
1201+         // Note that onChange was always broken when there was an 
1202+         // earlier setState() in a manual document capture phase 
1203+         // listener *in the same component*. But that's very rare. 
1204+         // Here we're testing that a *child* component doesn't break 
1205+         // the parent if this happens. 
1206+       } ; 
1207+       render ( )  { 
1208+         return  < div  /> ; 
1209+       } 
1210+     } 
1211+ 
1212+     class  Parent  extends  React . Component  { 
1213+       handleChange  =  val  =>  { 
1214+         didCallOnChange  =  true ; 
1215+       } ; 
1216+       render ( )  { 
1217+         return  ( 
1218+           < div > 
1219+             < Child  /> 
1220+             < input 
1221+               ref = { inputRef } 
1222+               type = "checkbox" 
1223+               checked = { true } 
1224+               onChange = { this . handleChange } 
1225+             /> 
1226+           </ div > 
1227+         ) ; 
1228+       } 
1229+     } 
1230+ 
1231+     ReactDOM . render ( < Parent  /> ,  container ) ; 
1232+     inputRef . current . dispatchEvent ( 
1233+       new  MouseEvent ( 'click' ,  { 
1234+         bubbles : true , 
1235+       } ) , 
1236+     ) ; 
1237+     expect ( didCallOnChange ) . toBe ( true ) ; 
1238+   } ) ; 
11811239} ) ; 
0 commit comments