Skip to content

Commit 7f2ca90

Browse files
committed
Add a failing tests (and update one test)
Currently, useSelector(selector) will call the passed selector twice on mount when it only needs to be called once on mount. This is unnecessary, and in the case of expensive selectors, can be a performance concern.
1 parent 86e962e commit 7f2ca90

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

test/hooks/useSelector.spec.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ describe('React', () => {
4545
})
4646

4747
expect(result.current).toEqual(0)
48-
expect(selector).toHaveBeenCalledTimes(2)
48+
expect(selector).toHaveBeenCalledTimes(1)
4949

5050
act(() => {
5151
store.dispatch({ type: '' })
5252
})
5353

5454
expect(result.current).toEqual(1)
55-
expect(selector).toHaveBeenCalledTimes(3)
55+
expect(selector).toHaveBeenCalledTimes(2)
5656
})
5757
})
5858

@@ -246,6 +246,39 @@ describe('React', () => {
246246

247247
expect(renderedItems.length).toBe(1)
248248
})
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+
})
249282
})
250283

251284
it('uses the latest selector', () => {

0 commit comments

Comments
 (0)