@@ -45,14 +45,14 @@ describe('React', () => {
45
45
} )
46
46
47
47
expect ( result . current ) . toEqual ( 0 )
48
- expect ( selector ) . toHaveBeenCalledTimes ( 2 )
48
+ expect ( selector ) . toHaveBeenCalledTimes ( 1 )
49
49
50
50
act ( ( ) => {
51
51
store . dispatch ( { type : '' } )
52
52
} )
53
53
54
54
expect ( result . current ) . toEqual ( 1 )
55
- expect ( selector ) . toHaveBeenCalledTimes ( 3 )
55
+ expect ( selector ) . toHaveBeenCalledTimes ( 2 )
56
56
} )
57
57
} )
58
58
@@ -246,6 +246,79 @@ describe('React', () => {
246
246
247
247
expect ( renderedItems . length ) . toBe ( 1 )
248
248
} )
249
+
250
+ it ( 'calls selector exactly once on mount and on update' , ( ) => {
251
+ store = createStore ( ( { count } = { count : 0 } ) => ( {
252
+ count : count + 1 ,
253
+ } ) )
254
+
255
+ let numCalls = 0
256
+ const selector = ( s ) => {
257
+ numCalls += 1
258
+ return s . count
259
+ }
260
+ const renderedItems = [ ]
261
+
262
+ const Comp = ( ) => {
263
+ const value = useSelector ( selector )
264
+ renderedItems . push ( value )
265
+ return < div />
266
+ }
267
+
268
+ rtl . render (
269
+ < ProviderMock store = { store } >
270
+ < Comp />
271
+ </ ProviderMock >
272
+ )
273
+
274
+ expect ( numCalls ) . toBe ( 1 )
275
+ expect ( renderedItems . length ) . toEqual ( 1 )
276
+
277
+ store . dispatch ( { type : '' } )
278
+
279
+ expect ( numCalls ) . toBe ( 2 )
280
+ expect ( renderedItems . length ) . toEqual ( 2 )
281
+ } )
282
+
283
+ it ( 'calls selector twice once on mount when state changes during render' , ( ) => {
284
+ store = createStore ( ( { count } = { count : 0 } ) => ( {
285
+ count : count + 1 ,
286
+ } ) )
287
+
288
+ let numCalls = 0
289
+ const selector = ( s ) => {
290
+ numCalls += 1
291
+ return s . count
292
+ }
293
+ const renderedItems = [ ]
294
+
295
+ const Child = ( ) => {
296
+ useLayoutEffect ( ( ) => {
297
+ store . dispatch ( { type : '' , count : 1 } )
298
+ } , [ ] )
299
+ return < div />
300
+ }
301
+
302
+ const Comp = ( ) => {
303
+ const value = useSelector ( selector )
304
+ renderedItems . push ( value )
305
+ return (
306
+ < div >
307
+ < Child />
308
+ </ div >
309
+ )
310
+ }
311
+
312
+ rtl . render (
313
+ < ProviderMock store = { store } >
314
+ < Comp />
315
+ </ ProviderMock >
316
+ )
317
+
318
+ // Selector first called on Comp mount, and then re-invoked after mount due to useLayoutEffect dispatching event
319
+ expect ( numCalls ) . toBe ( 2 )
320
+ expect ( renderedItems . length ) . toEqual ( 2 )
321
+ } )
249
322
} )
250
323
251
324
it ( 'uses the latest selector' , ( ) => {
0 commit comments