Skip to content

Commit 8a3ea9c

Browse files
committed
Add and use a countObjectKeys util
1 parent 306b1ef commit 8a3ea9c

File tree

9 files changed

+34
-28
lines changed

9 files changed

+34
-28
lines changed

packages/toolkit/src/query/core/buildInitiate.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type { BaseQueryError, QueryReturnValue } from '../baseQueryTypes'
2020
import type { QueryResultSelectorResult } from './buildSelectors'
2121
import type { Dispatch } from 'redux'
2222
import { isNotNullish } from '../utils/isNotNullish'
23+
import { countObjectKeys } from '../utils/countObjectKeys'
2324

2425
declare module './module' {
2526
export interface ApiEndpointQuery<
@@ -392,7 +393,7 @@ You must add the middleware for RTK-Query to function correctly!`
392393

393394
statePromise.then(() => {
394395
delete running[queryCacheKey]
395-
if (!Object.keys(running).length) {
396+
if (!countObjectKeys(running)) {
396397
runningQueries.delete(dispatch)
397398
}
398399
})
@@ -440,7 +441,7 @@ You must add the middleware for RTK-Query to function correctly!`
440441
running[requestId] = ret
441442
ret.then(() => {
442443
delete running[requestId]
443-
if (!Object.keys(running).length) {
444+
if (!countObjectKeys(running)) {
444445
runningMutations.delete(dispatch)
445446
}
446447
})
@@ -449,7 +450,7 @@ You must add the middleware for RTK-Query to function correctly!`
449450
ret.then(() => {
450451
if (running[fixedCacheKey] === ret) {
451452
delete running[fixedCacheKey]
452-
if (!Object.keys(running).length) {
453+
if (!countObjectKeys(running)) {
453454
runningMutations.delete(dispatch)
454455
}
455456
}

packages/toolkit/src/query/core/buildMiddleware/invalidationByTags.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
ApiMiddlewareInternalHandler,
1212
InternalMiddlewareState,
1313
} from './types'
14+
import { countObjectKeys } from '../../utils/countObjectKeys'
1415

1516
export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({
1617
reducerPath,
@@ -77,7 +78,7 @@ export const buildInvalidationByTagsHandler: InternalHandlerBuilder = ({
7778
internalState.currentSubscriptions[queryCacheKey] ?? {}
7879

7980
if (querySubState) {
80-
if (Object.keys(subscriptionSubState).length === 0) {
81+
if (countObjectKeys(subscriptionSubState) === 0) {
8182
mwApi.dispatch(
8283
removeQueryResult({
8384
queryCacheKey: queryCacheKey as QueryCacheKey,

packages/toolkit/src/query/core/buildMiddleware/windowEventHandling.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
InternalHandlerBuilder,
77
SubMiddlewareApi,
88
} from './types'
9+
import { countObjectKeys } from '../../utils/countObjectKeys'
910

1011
export const buildWindowEventHandler: InternalHandlerBuilder = ({
1112
reducerPath,
@@ -50,7 +51,7 @@ export const buildWindowEventHandler: InternalHandlerBuilder = ({
5051
state.config[type])
5152

5253
if (shouldRefetch) {
53-
if (Object.keys(subscriptionSubState).length === 0) {
54+
if (countObjectKeys(subscriptionSubState) === 0) {
5455
api.dispatch(
5556
removeQueryResult({
5657
queryCacheKey: queryCacheKey as QueryCacheKey,

packages/toolkit/src/query/react/module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
} from 'react-redux'
2323
import type { QueryKeys } from '../core/apiState'
2424
import type { PrefetchOptions } from '../core/module'
25+
import { countObjectKeys } from '../utils/countObjectKeys'
2526

2627
export const reactHooksModuleName = /* @__PURE__ */ Symbol()
2728
export type ReactHooksModule = typeof reactHooksModuleName
@@ -147,7 +148,7 @@ export const reactHooksModule = ({
147148
let warned = false
148149
for (const hookName of hookNames) {
149150
// warn for old hook options
150-
if (Object.keys(rest).length > 0) {
151+
if (countObjectKeys(rest) > 0) {
151152
if ((rest as Partial<typeof hooks>)[hookName]) {
152153
if (!warned) {
153154
console.warn(

packages/toolkit/src/query/tests/buildHooks.test.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import type { SerializedError } from '@reduxjs/toolkit'
3838
import { createListenerMiddleware, configureStore } from '@reduxjs/toolkit'
3939
import { delay } from '../../utils'
4040
import type { InternalMiddlewareState } from '../core/buildMiddleware/types'
41+
import { countObjectKeys } from '../utils/countObjectKeys'
4142

4243
// Just setup a temporary in-memory counter for tests that `getIncrementedAmount`.
4344
// This can be used to test how many renders happen due to data changes or
@@ -149,7 +150,7 @@ function getSubscriptions() {
149150
function getSubscriptionCount(key: string) {
150151
const subscriptions = getSubscriptions()
151152
const subscriptionsForQueryArg = subscriptions[key] ?? {}
152-
return Object.keys(subscriptionsForQueryArg).length
153+
return countObjectKeys(subscriptionsForQueryArg)
153154
}
154155

155156
beforeEach(() => {
@@ -1439,25 +1440,19 @@ describe('hooks tests', () => {
14391440

14401441
await screen.findByText(/isUninitialized/i)
14411442
expect(screen.queryByText('Yay')).toBeNull()
1442-
expect(Object.keys(storeRef.store.getState().api.mutations).length).toBe(
1443-
0
1444-
)
1443+
expect(countObjectKeys(storeRef.store.getState().api.mutations)).toBe(0)
14451444

14461445
userEvent.click(screen.getByRole('button', { name: 'trigger' }))
14471446

14481447
await screen.findByText(/isSuccess/i)
14491448
expect(screen.queryByText('Yay')).not.toBeNull()
1450-
expect(Object.keys(storeRef.store.getState().api.mutations).length).toBe(
1451-
1
1452-
)
1449+
expect(countObjectKeys(storeRef.store.getState().api.mutations)).toBe(1)
14531450

14541451
userEvent.click(screen.getByRole('button', { name: 'reset' }))
14551452

14561453
await screen.findByText(/isUninitialized/i)
14571454
expect(screen.queryByText('Yay')).toBeNull()
1458-
expect(Object.keys(storeRef.store.getState().api.mutations).length).toBe(
1459-
0
1460-
)
1455+
expect(countObjectKeys(storeRef.store.getState().api.mutations)).toBe(0)
14611456
})
14621457
})
14631458

packages/toolkit/src/query/tests/buildInitiate.test.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,6 @@ function getSubscriptions() {
3131
) as unknown as InternalMiddlewareState
3232
return internalState?.currentSubscriptions ?? {}
3333
}
34-
35-
function getSubscriptionCount(key: string) {
36-
const subscriptions = getSubscriptions()
37-
const subscriptionsForQueryArg = subscriptions[key] ?? {}
38-
return Object.keys(subscriptionsForQueryArg).length
39-
//return Object.keys(storeRef.store.getState().api.subscriptions[key] || {})
40-
//.length
41-
}
42-
4334
function isRequestSubscribed(key: string, requestId: string) {
4435
const subscriptions = getSubscriptions()
4536
return !!subscriptions?.[key]?.[requestId]

packages/toolkit/src/query/tests/cacheCollection.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
THIRTY_TWO_BIT_MAX_INT,
77
THIRTY_TWO_BIT_MAX_TIMER_SECONDS,
88
} from '../core/buildMiddleware/cacheCollection'
9+
import { countObjectKeys } from '../utils/countObjectKeys'
910

1011
beforeAll(() => {
1112
vi.useFakeTimers()
@@ -177,10 +178,10 @@ function storeForApi<
177178
let hadQueries = false
178179
store.subscribe(() => {
179180
const queryState = store.getState().api.queries
180-
if (hadQueries && Object.keys(queryState).length === 0) {
181+
if (hadQueries && countObjectKeys(queryState) === 0) {
181182
onCleanup()
182183
}
183-
hadQueries = hadQueries || Object.keys(queryState).length > 0
184+
hadQueries = hadQueries || countObjectKeys(queryState) > 0
184185
})
185186
return { api, store }
186187
}

packages/toolkit/src/query/tests/cleanup.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { createApi, QueryStatus } from '@reduxjs/toolkit/query/react'
77
import { render, waitFor, act, screen } from '@testing-library/react'
88
import { setupApiStore } from './helpers'
99
import { InternalMiddlewareState } from '../core/buildMiddleware/types'
10+
import { countObjectKeys } from '../utils/countObjectKeys'
1011

1112
const tick = () => new Promise((res) => setImmediate(res))
1213

@@ -207,7 +208,7 @@ test('Minimizes the number of subscription dispatches when multiple components a
207208

208209
const subscriptions = getSubscriptionsA()
209210

210-
expect(Object.keys(subscriptions!).length).toBe(NUM_LIST_ITEMS)
211+
expect(countObjectKeys(subscriptions!)).toBe(NUM_LIST_ITEMS)
211212

212213
expect(actionTypes).toEqual([
213214
'api/config/middlewareRegistered',
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Fast method for counting an object's keys
2+
// without resorting to `Object.keys(obj).length
3+
// Will this make a big difference in perf? Probably not
4+
// But we can save a few allocations.
5+
6+
export function countObjectKeys(obj: Record<any, any>) {
7+
let count = 0
8+
9+
for (const _key in obj) {
10+
count++
11+
}
12+
13+
return count
14+
}

0 commit comments

Comments
 (0)