@@ -72,14 +72,14 @@ describe('React', () => {
7272 } )
7373
7474 expect ( result . current ) . toEqual ( 0 )
75- expect ( selector ) . toHaveBeenCalledTimes ( 2 )
75+ expect ( selector ) . toHaveBeenCalledTimes ( 1 )
7676
7777 act ( ( ) => {
7878 normalStore . dispatch ( { type : '' } )
7979 } )
8080
8181 expect ( result . current ) . toEqual ( 1 )
82- expect ( selector ) . toHaveBeenCalledTimes ( 3 )
82+ expect ( selector ) . toHaveBeenCalledTimes ( 2 )
8383 } )
8484 } )
8585
@@ -283,6 +283,85 @@ describe('React', () => {
283283
284284 expect ( renderedItems . length ) . toBe ( 1 )
285285 } )
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+ } )
286365 } )
287366
288367 it ( 'uses the latest selector' , ( ) => {
0 commit comments