@@ -117,6 +117,72 @@ describe('ReactHooks', () => {
117
117
expect ( root ) . toFlushAndYield ( [ 'Parent: 1, 2' ] ) ;
118
118
} ) ;
119
119
120
+ it ( 'bails out in render phase if all the state is the same and props bail out with memo' , ( ) => {
121
+ const { useState, memo} = React ;
122
+
123
+ function Child ( { text} ) {
124
+ ReactTestRenderer . unstable_yield ( 'Child: ' + text ) ;
125
+ return text ;
126
+ }
127
+
128
+ let setCounter1 ;
129
+ let setCounter2 ;
130
+ function Parent ( { theme} ) {
131
+ const [ counter1 , _setCounter1 ] = useState ( 0 ) ;
132
+ setCounter1 = _setCounter1 ;
133
+ const [ counter2 , _setCounter2 ] = useState ( 0 ) ;
134
+ setCounter2 = _setCounter2 ;
135
+
136
+ const text = `${ counter1 } , ${ counter2 } (${ theme } )` ;
137
+ ReactTestRenderer . unstable_yield ( `Parent: ${ text } ` ) ;
138
+ return < Child text = { text } /> ;
139
+ }
140
+
141
+ Parent = memo ( Parent ) ;
142
+
143
+ const root = ReactTestRenderer . create ( null , { unstable_isConcurrent : true } ) ;
144
+ root . update ( < Parent theme = "light" /> ) ;
145
+ expect ( root ) . toFlushAndYield ( [
146
+ 'Parent: 0, 0 (light)' ,
147
+ 'Child: 0, 0 (light)' ,
148
+ ] ) ;
149
+ expect ( root ) . toMatchRenderedOutput ( '0, 0 (light)' ) ;
150
+
151
+ // Normal update
152
+ setCounter1 ( 1 ) ;
153
+ setCounter2 ( 1 ) ;
154
+ expect ( root ) . toFlushAndYield ( [
155
+ 'Parent: 1, 1 (light)' ,
156
+ 'Child: 1, 1 (light)' ,
157
+ ] ) ;
158
+
159
+ // Update that bails out.
160
+ setCounter1 ( 1 ) ;
161
+ expect ( root ) . toFlushAndYield ( [ 'Parent: 1, 1 (light)' ] ) ;
162
+
163
+ // This time, one of the state updates but the other one doesn't. So we
164
+ // can't bail out.
165
+ setCounter1 ( 1 ) ;
166
+ setCounter2 ( 2 ) ;
167
+ expect ( root ) . toFlushAndYield ( [
168
+ 'Parent: 1, 2 (light)' ,
169
+ 'Child: 1, 2 (light)' ,
170
+ ] ) ;
171
+
172
+ // Updates bail out, but component still renders because props
173
+ // have changed
174
+ setCounter1 ( 1 ) ;
175
+ setCounter2 ( 2 ) ;
176
+ root . update ( < Parent theme = "dark" /> ) ;
177
+ expect ( root ) . toFlushAndYield ( [ 'Parent: 1, 2 (dark)' , 'Child: 1, 2 (dark)' ] ) ;
178
+
179
+ // Both props and state bail out
180
+ setCounter1 ( 1 ) ;
181
+ setCounter2 ( 2 ) ;
182
+ root . update ( < Parent theme = "dark" /> ) ;
183
+ expect ( root ) . toFlushAndYield ( [ 'Parent: 1, 2 (dark)' ] ) ;
184
+ } ) ;
185
+
120
186
it ( 'never bails out if context has changed' , ( ) => {
121
187
const { useState, useLayoutEffect, useContext} = React ;
122
188
0 commit comments