Skip to content

Commit c8233fc

Browse files
committed
Merge branch 'master' of https://github.com/reduxjs/redux-toolkit into fix-type-portability-issues
2 parents fc9b3b8 + a9362fb commit c8233fc

File tree

8 files changed

+94
-30
lines changed

8 files changed

+94
-30
lines changed

.github/workflows/tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,11 @@ jobs:
9292
- name: Install build artifact
9393
run: yarn workspace @reduxjs/toolkit add $(pwd)/package.tgz
9494

95-
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.mts ./src/tests/*.* ./src/query/tests/*.*
95+
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json
9696

9797
- name: Run tests, against dist
98+
env:
99+
TEST_DIST: true
98100
run: yarn test
99101

100102
- name: Run type tests with `moduleResolution Bundler`
@@ -188,9 +190,11 @@ jobs:
188190
- name: Show installed RTK versions
189191
run: yarn info @reduxjs/toolkit
190192

191-
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json ./vitest.config.mts ./src/tests/*.* ./src/query/tests/*.*
193+
- run: sed -i -e /@remap-prod-remove-line/d ./tsconfig.base.json
192194

193195
- name: Test types
196+
env:
197+
TEST_DIST: true
194198
run: |
195199
yarn tsc --version
196200
yarn type-tests

packages/toolkit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reduxjs/toolkit",
3-
"version": "2.2.5",
3+
"version": "2.2.6",
44
"description": "The official, opinionated, batteries-included toolset for efficient Redux development",
55
"author": "Mark Erikson <mark@isquaredsoftware.com>",
66
"license": "MIT",

packages/toolkit/src/entities/sorted_state_adapter.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { current, isDraft } from 'immer'
21
import type {
32
IdSelector,
43
Comparer,
@@ -70,9 +69,7 @@ export function createSortedStateAdapter<T, Id extends EntityId>(
7069
): void {
7170
newEntities = ensureEntitiesArray(newEntities)
7271

73-
const existingKeys = new Set<Id>(
74-
existingIds ?? (current(state.ids) as Id[]),
75-
)
72+
const existingKeys = new Set<Id>(existingIds ?? getCurrent(state.ids))
7673

7774
const models = newEntities.filter(
7875
(model) => !existingKeys.has(selectIdValue(model, selectId)),
@@ -176,7 +173,7 @@ export function createSortedStateAdapter<T, Id extends EntityId>(
176173
return false
177174
}
178175

179-
for (let i = 0; i < a.length && i < b.length; i++) {
176+
for (let i = 0; i < a.length; i++) {
180177
if (a[i] === b[i]) {
181178
continue
182179
}
@@ -192,20 +189,20 @@ export function createSortedStateAdapter<T, Id extends EntityId>(
192189
replacedIds?: boolean,
193190
) => void
194191

195-
const mergeInsertion: MergeFunction = (
192+
const mergeFunction: MergeFunction = (
196193
state,
197194
addedItems,
198195
appliedUpdates,
199196
replacedIds,
200197
) => {
201-
const currentEntities = getCurrent(state.entities) as Record<Id, T>
202-
const currentIds = getCurrent(state.ids) as Id[]
198+
const currentEntities = getCurrent(state.entities)
199+
const currentIds = getCurrent(state.ids)
203200

204201
const stateEntities = state.entities as Record<Id, T>
205202

206-
let ids = currentIds
203+
let ids: Iterable<Id> = currentIds
207204
if (replacedIds) {
208-
ids = Array.from(new Set(currentIds))
205+
ids = new Set(currentIds)
209206
}
210207

211208
let sortedEntities: T[] = []
@@ -242,8 +239,6 @@ export function createSortedStateAdapter<T, Id extends EntityId>(
242239
}
243240
}
244241

245-
const mergeFunction: MergeFunction = mergeInsertion
246-
247242
return {
248243
removeOne,
249244
removeMany,

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,31 @@ describe('Sorted State Adapter', () => {
808808
)
809809
})
810810

811+
it('should not throw an Immer `current` error when the adapter is called twice', () => {
812+
const book1: BookModel = { id: 'a', title: 'First' }
813+
const book2: BookModel = { id: 'b', title: 'Second' }
814+
const initialState = adapter.getInitialState()
815+
const booksSlice = createSlice({
816+
name: 'books',
817+
initialState,
818+
reducers: {
819+
testCurrentBehavior(state, action: PayloadAction<BookModel>) {
820+
// Will overwrite `state.ids` with a plain array
821+
adapter.removeAll(state)
822+
823+
// will call `splitAddedUpdatedEntities` and call `current(state.ids)`
824+
adapter.addOne(state, book1)
825+
adapter.addOne(state, book2)
826+
},
827+
},
828+
})
829+
830+
booksSlice.reducer(
831+
initialState,
832+
booksSlice.actions.testCurrentBehavior(book1),
833+
)
834+
})
835+
811836
describe('can be used mutably when wrapped in createNextState', () => {
812837
test('removeAll', () => {
813838
const withTwo = adapter.addMany(state, [TheGreatGatsby, AnimalFarm])

packages/toolkit/src/entities/unsorted_state_adapter.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,7 @@ export function createUnsortedStateAdapter<T, Id extends EntityId>(
145145
// Spreads ignore falsy values, so this works even if there isn't
146146
// an existing update already at this key
147147
changes: {
148-
...(updatesPerEntity[update.id]
149-
? updatesPerEntity[update.id].changes
150-
: null),
148+
...updatesPerEntity[update.id]?.changes,
151149
...update.changes,
152150
},
153151
}

packages/toolkit/src/entities/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { current, isDraft } from 'immer'
1+
import { Draft, current, isDraft } from 'immer'
22
import type {
33
IdSelector,
44
Update,
@@ -36,8 +36,8 @@ export function ensureEntitiesArray<T, Id extends EntityId>(
3636
return entities
3737
}
3838

39-
export function getCurrent<T>(value: T): T {
40-
return isDraft(value) ? current(value) : value
39+
export function getCurrent<T>(value: T | Draft<T>): T {
40+
return (isDraft(value) ? current(value) : value) as T
4141
}
4242

4343
export function splitAddedUpdatedEntities<T, Id extends EntityId>(
@@ -47,7 +47,7 @@ export function splitAddedUpdatedEntities<T, Id extends EntityId>(
4747
): [T[], Update<T, Id>[], Id[]] {
4848
newEntities = ensureEntitiesArray(newEntities)
4949

50-
const existingIdsArray = getCurrent(state.ids) as Id[]
50+
const existingIdsArray = getCurrent(state.ids)
5151
const existingIds = new Set<Id>(existingIdsArray)
5252

5353
const added: T[] = []

packages/toolkit/src/tests/configureStore.test.ts

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ describe('configureStore', async () => {
3939
expect.any(Function),
4040
)
4141
expect(redux.applyMiddleware).toHaveBeenCalled()
42-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
42+
if (process.env.TEST_DIST) {
43+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
44+
} else {
45+
expect(composeWithDevToolsSpy).toHaveBeenCalledTimes(2)
46+
}
4347
})
4448
})
4549

@@ -53,7 +57,11 @@ describe('configureStore', async () => {
5357
expect(configureStore({ reducer })).toBeInstanceOf(Object)
5458
expect(redux.combineReducers).toHaveBeenCalledWith(reducer)
5559
expect(redux.applyMiddleware).toHaveBeenCalled()
56-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
60+
if (process.env.TEST_DIST) {
61+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
62+
} else {
63+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
64+
}
5765
expect(redux.createStore).toHaveBeenCalledWith(
5866
expect.any(Function),
5967
undefined,
@@ -76,7 +84,11 @@ describe('configureStore', async () => {
7684
configureStore({ middleware: () => new Tuple(), reducer }),
7785
).toBeInstanceOf(Object)
7886
expect(redux.applyMiddleware).toHaveBeenCalledWith()
79-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
87+
if (process.env.TEST_DIST) {
88+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
89+
} else {
90+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
91+
}
8092
expect(redux.createStore).toHaveBeenCalledWith(
8193
reducer,
8294
undefined,
@@ -105,7 +117,11 @@ describe('configureStore', async () => {
105117
expect.any(Function), // serializableCheck
106118
expect.any(Function), // actionCreatorCheck
107119
)
108-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
120+
if (process.env.TEST_DIST) {
121+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
122+
} else {
123+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
124+
}
109125
expect(redux.createStore).toHaveBeenCalledWith(
110126
reducer,
111127
undefined,
@@ -142,7 +158,11 @@ describe('configureStore', async () => {
142158
configureStore({ middleware: () => new Tuple(thank), reducer }),
143159
).toBeInstanceOf(Object)
144160
expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
145-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
161+
if (process.env.TEST_DIST) {
162+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
163+
} else {
164+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
165+
}
146166
expect(redux.createStore).toHaveBeenCalledWith(
147167
reducer,
148168
undefined,
@@ -197,7 +217,13 @@ describe('configureStore', async () => {
197217
Object,
198218
)
199219
expect(redux.applyMiddleware).toHaveBeenCalled()
200-
expect(composeWithDevToolsSpy).toHaveBeenCalledWith(options) // @remap-prod-remove-line
220+
if (process.env.TEST_DIST) {
221+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
222+
} else {
223+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
224+
225+
expect(composeWithDevToolsSpy).toHaveBeenLastCalledWith(options)
226+
}
201227
expect(redux.createStore).toHaveBeenCalledWith(
202228
reducer,
203229
undefined,
@@ -210,7 +236,11 @@ describe('configureStore', async () => {
210236
it('calls createStore with preloadedState', () => {
211237
expect(configureStore({ reducer })).toBeInstanceOf(Object)
212238
expect(redux.applyMiddleware).toHaveBeenCalled()
213-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
239+
if (process.env.TEST_DIST) {
240+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
241+
} else {
242+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
243+
}
214244
expect(redux.createStore).toHaveBeenCalledWith(
215245
reducer,
216246
undefined,
@@ -241,7 +271,11 @@ describe('configureStore', async () => {
241271
}),
242272
).toBeInstanceOf(Object)
243273
expect(redux.applyMiddleware).toHaveBeenCalled()
244-
expect(composeWithDevToolsSpy).toHaveBeenCalled() // @remap-prod-remove-line
274+
if (process.env.TEST_DIST) {
275+
expect(composeWithDevToolsSpy).not.toHaveBeenCalled()
276+
} else {
277+
expect(composeWithDevToolsSpy).toHaveBeenCalledOnce()
278+
}
245279
expect(redux.createStore).toHaveBeenCalledWith(
246280
reducer,
247281
undefined,

packages/toolkit/vitest.config.mts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ const __dirname = path.dirname(__filename)
1010
export default defineConfig({
1111
plugins: [tsconfigPaths({ root: __dirname })],
1212
test: {
13+
alias: process.env.TEST_DIST
14+
? {
15+
'@reduxjs/toolkit': new URL(
16+
'node_modules/@reduxjs/toolkit',
17+
import.meta.url,
18+
).pathname,
19+
}
20+
: undefined,
1321
globals: true,
1422
environment: 'jsdom',
1523
setupFiles: ['./vitest.setup.ts'],

0 commit comments

Comments
 (0)