Skip to content

Commit fd39b8e

Browse files
authored
Merge pull request #5097 from demyanm/bugfix/5096-process-multiple-add-for-the-same-new-entity
fix(entityAdapter): ensure sorted addMany keeps first occurrence of duplicate ids
2 parents 98cdfb2 + 2d8031f commit fd39b8e

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

packages/toolkit/src/entities/sorted_state_adapter.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,14 @@ export function createSortedStateAdapter<T, Id extends EntityId>(
7070
newEntities = ensureEntitiesArray(newEntities)
7171

7272
const existingKeys = new Set<Id>(existingIds ?? getCurrent(state.ids))
73-
73+
const addedKeys = new Set<Id>();
7474
const models = newEntities.filter(
75-
(model) => !existingKeys.has(selectIdValue(model, selectId)),
75+
(model) => {
76+
const modelId = selectIdValue(model, selectId);
77+
const notAdded = !addedKeys.has(modelId);
78+
if (notAdded) addedKeys.add(modelId);
79+
return !existingKeys.has(modelId) && notAdded;
80+
}
7681
)
7782

7883
if (models.length !== 0) {

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,25 @@ describe('Sorted State Adapter', () => {
588588
})
589589
})
590590

591+
it('should work consistent with Unsorted State Adapter adding duplicate ids', () => {
592+
const unsortedAdaptor = createEntityAdapter({
593+
selectId: (book: BookModel) => book.id
594+
});
595+
596+
const firstEntry = {id: AClockworkOrange.id, author: TheHobbit.author }
597+
const secondEntry = {id: AClockworkOrange.id, title: 'Zack' }
598+
const withNothingSorted = adapter.setAll(state, []);
599+
const withNothingUnsorted = unsortedAdaptor.setAll(state, []);
600+
const withOneSorted = adapter.addMany(withNothingSorted, [
601+
{ ...AClockworkOrange, ...firstEntry }, {...AClockworkOrange, ...secondEntry}
602+
])
603+
const withOneUnsorted = adapter.addMany(withNothingUnsorted, [
604+
{ ...AClockworkOrange, ...firstEntry }, {...AClockworkOrange, ...secondEntry}
605+
])
606+
607+
expect(withOneSorted).toEqual(withOneUnsorted);
608+
})
609+
591610
it('should let you set many entities in the state when passing in a dictionary', () => {
592611
const changeWithoutAuthor = { id: TheHobbit.id, title: 'Silmarillion' }
593612
const withMany = adapter.setAll(state, [TheHobbit])

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ describe('Unsorted State Adapter', () => {
8989
})
9090
})
9191

92+
it('should let you add the only first occurrence for duplicate ids', () => {
93+
const firstEntry = {id: AClockworkOrange.id, author: TheHobbit.author }
94+
const secondEntry = {id: AClockworkOrange.id, title: 'Zack' }
95+
const withOne = adapter.setAll(state, [TheGreatGatsby])
96+
const withMany = adapter.addMany(withOne, [
97+
{ ...AClockworkOrange, ...firstEntry }, {...AClockworkOrange, ...secondEntry}
98+
])
99+
100+
expect(withMany).toEqual({
101+
ids: [TheGreatGatsby.id, AClockworkOrange.id],
102+
entities: {
103+
[TheGreatGatsby.id]: TheGreatGatsby,
104+
[AClockworkOrange.id]: {
105+
...AClockworkOrange,
106+
...firstEntry,
107+
},
108+
},
109+
})
110+
})
111+
92112
it('should remove existing and add new ones on setAll', () => {
93113
const withOneEntity = adapter.addOne(state, TheGreatGatsby)
94114

0 commit comments

Comments
 (0)