diff --git a/src/hooks/useSelector.ts b/src/hooks/useSelector.ts
index 0415e908b..e4c232e7d 100644
--- a/src/hooks/useSelector.ts
+++ b/src/hooks/useSelector.ts
@@ -90,7 +90,6 @@ export function createSelectorHook(context = ReactReduxContext): UseSelector {
const selected = selector(state)
if (process.env.NODE_ENV !== 'production') {
const finalStabilityCheck =
- // are we safe to use ?? here?
typeof stabilityCheck === 'undefined'
? globalStabilityCheck
: stabilityCheck
@@ -114,7 +113,6 @@ export function createSelectorHook(context = ReactReduxContext): UseSelector {
}
}
const finalNoopCheck =
- // are we safe to use ?? here?
typeof noopCheck === 'undefined' ? globalNoopCheck : noopCheck
if (
finalNoopCheck === 'always' ||
diff --git a/test/hooks/useSelector.spec.tsx b/test/hooks/useSelector.spec.tsx
index 20d1e5464..500aded64 100644
--- a/test/hooks/useSelector.spec.tsx
+++ b/test/hooks/useSelector.spec.tsx
@@ -28,13 +28,19 @@ import type { FunctionComponent, DispatchWithoutAction, ReactNode } from 'react'
import type { Store, AnyAction } from 'redux'
import { UseSelectorOptions } from '../../src/hooks/useSelector'
-// most of these tests depend on selectors being run once, which stabilityCheck doesn't do
-// rather than specify it every time, let's make a new "default" here
+// disable checks by default
function ProviderMock = AnyAction, S = unknown>({
stabilityCheck = 'never',
+ noopCheck = 'never',
...props
}: ProviderProps) {
- return
+ return (
+
+ )
}
const IS_REACT_18 = React.version.startsWith('18')
@@ -739,36 +745,38 @@ describe('React', () => {
})
describe('Development mode checks', () => {
+ const consoleSpy = jest
+ .spyOn(console, 'warn')
+ .mockImplementation(() => {})
+ afterEach(() => {
+ consoleSpy.mockClear()
+ })
+ afterAll(() => {
+ consoleSpy.mockRestore()
+ })
+
+ const RenderSelector = ({
+ selector,
+ options,
+ }: {
+ selector: (state: NormalStateType) => unknown
+ options?: UseSelectorOptions
+ }) => {
+ useSelector(selector, options)
+ return null
+ }
describe('selector result stability check', () => {
const selector = jest.fn((state: NormalStateType) => state.count)
- const consoleSpy = jest
- .spyOn(console, 'warn')
- .mockImplementation(() => {})
afterEach(() => {
- consoleSpy.mockClear()
selector.mockClear()
})
- afterAll(() => {
- consoleSpy.mockRestore()
- })
-
- const RenderSelector = ({
- selector,
- options,
- }: {
- selector: (state: NormalStateType) => unknown
- options?: UseSelectorOptions
- }) => {
- useSelector(selector, options)
- return null
- }
it('calls a selector twice, and warns in console if it returns a different result', () => {
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(2)
@@ -780,9 +788,9 @@ describe('React', () => {
const unstableSelector = jest.fn(() => Math.random())
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(2)
@@ -806,12 +814,12 @@ describe('React', () => {
}))
rtl.render(
-
+
-
+
)
expect(unstableSelector).toHaveBeenCalledTimes(2)
@@ -819,9 +827,9 @@ describe('React', () => {
})
it('by default will only check on first selector call', () => {
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(2)
@@ -834,9 +842,9 @@ describe('React', () => {
})
it('disables check if context or hook specifies', () => {
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(1)
@@ -846,21 +854,21 @@ describe('React', () => {
selector.mockClear()
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(1)
})
it('always runs check if context or hook specifies', () => {
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(2)
@@ -876,12 +884,12 @@ describe('React', () => {
selector.mockClear()
rtl.render(
-
+
-
+
)
expect(selector).toHaveBeenCalledTimes(2)
@@ -893,6 +901,29 @@ describe('React', () => {
expect(selector).toHaveBeenCalledTimes(4)
})
})
+ describe('no-op selector check', () => {
+ it('warns for selectors that return the entire root state', () => {
+ rtl.render(
+
+ state.count} />
+
+ )
+
+ expect(consoleSpy).not.toHaveBeenCalled()
+
+ rtl.cleanup()
+
+ rtl.render(
+
+ state} />
+
+ )
+
+ expect(consoleSpy).toHaveBeenCalledWith(
+ expect.stringContaining('returned the root state when called.')
+ )
+ })
+ })
})
})