@@ -72,14 +72,14 @@ describe('React', () => {
72
72
} )
73
73
74
74
expect ( result . current ) . toEqual ( 0 )
75
- expect ( selector ) . toHaveBeenCalledTimes ( 2 )
75
+ expect ( selector ) . toHaveBeenCalledTimes ( 1 )
76
76
77
77
act ( ( ) => {
78
78
normalStore . dispatch ( { type : '' } )
79
79
} )
80
80
81
81
expect ( result . current ) . toEqual ( 1 )
82
- expect ( selector ) . toHaveBeenCalledTimes ( 3 )
82
+ expect ( selector ) . toHaveBeenCalledTimes ( 2 )
83
83
} )
84
84
} )
85
85
@@ -283,6 +283,85 @@ describe('React', () => {
283
283
284
284
expect ( renderedItems . length ) . toBe ( 1 )
285
285
} )
286
+
287
+ it ( 'calls selector exactly once on mount and on update' , ( ) => {
288
+ interface StateType {
289
+ count : number
290
+ }
291
+ const store = createStore ( ( { count } : StateType = { count : 0 } ) => ( {
292
+ count : count + 1 ,
293
+ } ) )
294
+
295
+ let numCalls = 0
296
+ const selector = ( s : StateType ) => {
297
+ numCalls += 1
298
+ return s . count
299
+ }
300
+ const renderedItems = [ ]
301
+
302
+ const Comp = ( ) => {
303
+ const value = useSelector ( selector )
304
+ renderedItems . push ( value )
305
+ return < div />
306
+ }
307
+
308
+ rtl . render (
309
+ < ProviderMock store = { store } >
310
+ < Comp />
311
+ </ ProviderMock >
312
+ )
313
+
314
+ expect ( numCalls ) . toBe ( 1 )
315
+ expect ( renderedItems . length ) . toEqual ( 1 )
316
+
317
+ store . dispatch ( { type : '' } )
318
+
319
+ expect ( numCalls ) . toBe ( 2 )
320
+ expect ( renderedItems . length ) . toEqual ( 2 )
321
+ } )
322
+
323
+ it ( 'calls selector twice once on mount when state changes during render' , ( ) => {
324
+ interface StateType {
325
+ count : number
326
+ }
327
+ const store = createStore ( ( { count } : StateType = { count : 0 } ) => ( {
328
+ count : count + 1 ,
329
+ } ) )
330
+
331
+ let numCalls = 0
332
+ const selector = ( s : StateType ) => {
333
+ numCalls += 1
334
+ return s . count
335
+ }
336
+ const renderedItems = [ ]
337
+
338
+ const Child = ( ) => {
339
+ useLayoutEffect ( ( ) => {
340
+ store . dispatch ( { type : '' , count : 1 } )
341
+ } , [ ] )
342
+ return < div />
343
+ }
344
+
345
+ const Comp = ( ) => {
346
+ const value = useSelector ( selector )
347
+ renderedItems . push ( value )
348
+ return (
349
+ < div >
350
+ < Child />
351
+ </ div >
352
+ )
353
+ }
354
+
355
+ rtl . render (
356
+ < ProviderMock store = { store } >
357
+ < Comp />
358
+ </ ProviderMock >
359
+ )
360
+
361
+ // Selector first called on Comp mount, and then re-invoked after mount due to useLayoutEffect dispatching event
362
+ expect ( numCalls ) . toBe ( 2 )
363
+ expect ( renderedItems . length ) . toEqual ( 2 )
364
+ } )
286
365
} )
287
366
288
367
it ( 'uses the latest selector' , ( ) => {
0 commit comments