Skip to content

Commit 38a739a

Browse files
author
ben.durrant
committed
Allow passing a custom instance of createSelector to getSelectors
1 parent c717d8e commit 38a739a

File tree

3 files changed

+48
-19
lines changed

3 files changed

+48
-19
lines changed

packages/toolkit/src/entities/models.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { PayloadAction } from '../createAction'
22
import type { IsAny } from '../tsHelpers'
3+
import type { AnyCreateSelectorFunction } from './state_selectors'
34

45
/**
56
* @public
@@ -164,8 +165,12 @@ export interface EntityAdapter<T> extends EntityStateAdapter<T> {
164165
sortComparer: false | Comparer<T>
165166
getInitialState(): EntityState<T>
166167
getInitialState<S extends object>(state: S): EntityState<T> & S
167-
getSelectors(): EntitySelectors<T, EntityState<T>>
168+
getSelectors(
169+
selectState?: undefined,
170+
createSelector?: AnyCreateSelectorFunction
171+
): EntitySelectors<T, EntityState<T>>
168172
getSelectors<V>(
169-
selectState: (state: V) => EntityState<T>
173+
selectState: (state: V) => EntityState<T>,
174+
createSelector?: AnyCreateSelectorFunction
170175
): EntitySelectors<T, V>
171176
}

packages/toolkit/src/entities/state_selectors.ts

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Selector } from 'reselect'
1+
import type { CreateSelectorFunction, Selector } from 'reselect'
22
import { createDraftSafeSelector } from '../createDraftSafeSelector'
33
import type {
44
EntityState,
@@ -7,19 +7,29 @@ import type {
77
EntityId,
88
} from './models'
99

10+
export type AnyCreateSelectorFunction = CreateSelectorFunction<
11+
(...args: unknown[]) => unknown,
12+
<F extends (...args: any[]) => any>(func: F) => F
13+
>
14+
1015
export function createSelectorsFactory<T>() {
11-
function getSelectors(): EntitySelectors<T, EntityState<T>>
16+
function getSelectors(
17+
selectState?: undefined,
18+
createSelector?: AnyCreateSelectorFunction
19+
): EntitySelectors<T, EntityState<T>>
1220
function getSelectors<V>(
13-
selectState: (state: V) => EntityState<T>
21+
selectState: (state: V) => EntityState<T>,
22+
createSelector?: AnyCreateSelectorFunction
1423
): EntitySelectors<T, V>
1524
function getSelectors<V>(
16-
selectState?: (state: V) => EntityState<T>
25+
selectState?: (state: V) => EntityState<T>,
26+
createSelector: AnyCreateSelectorFunction = createDraftSafeSelector
1727
): EntitySelectors<T, any> {
1828
const selectIds = (state: EntityState<T>) => state.ids
1929

2030
const selectEntities = (state: EntityState<T>) => state.entities
2131

22-
const selectAll = createDraftSafeSelector(
32+
const selectAll = createSelector(
2333
selectIds,
2434
selectEntities,
2535
(ids, entities): T[] => ids.map((id) => entities[id]!)
@@ -29,33 +39,29 @@ export function createSelectorsFactory<T>() {
2939

3040
const selectById = (entities: Dictionary<T>, id: EntityId) => entities[id]
3141

32-
const selectTotal = createDraftSafeSelector(selectIds, (ids) => ids.length)
42+
const selectTotal = createSelector(selectIds, (ids) => ids.length)
3343

3444
if (!selectState) {
3545
return {
3646
selectIds,
3747
selectEntities,
3848
selectAll,
3949
selectTotal,
40-
selectById: createDraftSafeSelector(
41-
selectEntities,
42-
selectId,
43-
selectById
44-
),
50+
selectById: createSelector(selectEntities, selectId, selectById),
4551
}
4652
}
4753

48-
const selectGlobalizedEntities = createDraftSafeSelector(
54+
const selectGlobalizedEntities = createSelector(
4955
selectState as Selector<V, EntityState<T>>,
5056
selectEntities
5157
)
5258

5359
return {
54-
selectIds: createDraftSafeSelector(selectState, selectIds),
60+
selectIds: createSelector(selectState, selectIds),
5561
selectEntities: selectGlobalizedEntities,
56-
selectAll: createDraftSafeSelector(selectState, selectAll),
57-
selectTotal: createDraftSafeSelector(selectState, selectTotal),
58-
selectById: createDraftSafeSelector(
62+
selectAll: createSelector(selectState, selectAll),
63+
selectTotal: createSelector(selectState, selectTotal),
64+
selectById: createSelector(
5965
selectGlobalizedEntities,
6066
selectId,
6167
selectById

packages/toolkit/src/entities/tests/state_selectors.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import { createDraftSafeSelectorCreator } from '../../createDraftSafeSelector'
12
import type { EntityAdapter, EntityState } from '../index'
23
import { createEntityAdapter } from '../index'
34
import type { EntitySelectors } from '../models'
45
import type { BookModel } from './fixtures/book'
56
import { AClockworkOrange, AnimalFarm, TheGreatGatsby } from './fixtures/book'
67
import type { Selector } from 'reselect'
7-
import { createSelector } from 'reselect'
8+
import { createSelector, weakMapMemoize } from 'reselect'
9+
import { vi } from 'vitest'
810

911
describe('Entity State Selectors', () => {
1012
describe('Composed Selectors', () => {
@@ -122,6 +124,22 @@ describe('Entity State Selectors', () => {
122124
expect(second).toBe(AnimalFarm)
123125
})
124126
})
127+
describe('custom createSelector instance', () => {
128+
it('should use the custom createSelector function if provided', () => {
129+
const memoizeSpy = vi.fn(weakMapMemoize)
130+
const createCustomSelector = createDraftSafeSelectorCreator(memoizeSpy)
131+
132+
const adapter = createEntityAdapter({
133+
selectId: (book: BookModel) => book.id,
134+
})
135+
136+
adapter.getSelectors(undefined, createCustomSelector)
137+
138+
expect(memoizeSpy).toHaveBeenCalled()
139+
140+
memoizeSpy.mockClear()
141+
})
142+
})
125143
})
126144

127145
function expectType<T>(t: T) {

0 commit comments

Comments
 (0)