Skip to content

Commit d499052

Browse files
committed
Simplify state adapter logic using Immer
- Removed all references to DidMutate enum - Removed unneeded logic that only checked if state was mutated
1 parent 46088ec commit d499052

File tree

3 files changed

+92
-161
lines changed

3 files changed

+92
-161
lines changed

src/entities/sorted_state_adapter.ts

Lines changed: 46 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
Update,
77
EntityMap
88
} from './models'
9-
import { createStateOperator, DidMutate } from './state_adapter'
9+
import { createStateOperator } from './state_adapter'
1010
import { createUnsortedStateAdapter } from './unsorted_state_adapter'
1111
import { selectIdValue } from './utils'
1212

@@ -21,37 +21,32 @@ export function createSortedStateAdapter<T>(selectId: any, sort: any): any {
2121
selectId
2222
)
2323

24-
function addOneMutably(entity: T, state: R): DidMutate
25-
function addOneMutably(entity: any, state: any): DidMutate {
24+
function addOneMutably(entity: T, state: R): void
25+
function addOneMutably(entity: any, state: any): void {
2626
return addManyMutably([entity], state)
2727
}
2828

29-
function addManyMutably(newModels: T[], state: R): DidMutate
30-
function addManyMutably(newModels: any[], state: any): DidMutate {
29+
function addManyMutably(newModels: T[], state: R): void
30+
function addManyMutably(newModels: any[], state: any): void {
3131
const models = newModels.filter(
3232
model => !(selectIdValue(model, selectId) in state.entities)
3333
)
3434

35-
if (models.length === 0) {
36-
return DidMutate.None
37-
} else {
35+
if (models.length !== 0) {
3836
merge(models, state)
39-
return DidMutate.Both
4037
}
4138
}
4239

43-
function setAllMutably(models: T[], state: R): DidMutate
44-
function setAllMutably(models: any[], state: any): DidMutate {
40+
function setAllMutably(models: T[], state: R): void
41+
function setAllMutably(models: any[], state: any): void {
4542
state.entities = {}
4643
state.ids = []
4744

4845
addManyMutably(models, state)
49-
50-
return DidMutate.Both
5146
}
5247

53-
function updateOneMutably(update: Update<T>, state: R): DidMutate
54-
function updateOneMutably(update: any, state: any): DidMutate {
48+
function updateOneMutably(update: Update<T>, state: R): void
49+
function updateOneMutably(update: any, state: any): void {
5550
return updateManyMutably([update], state)
5651
}
5752

@@ -72,43 +67,19 @@ export function createSortedStateAdapter<T>(selectId: any, sort: any): any {
7267
return newKey !== update.id
7368
}
7469

75-
function updateManyMutably(updates: Update<T>[], state: R): DidMutate
76-
function updateManyMutably(updates: any[], state: any): DidMutate {
70+
function updateManyMutably(updates: Update<T>[], state: R): void
71+
function updateManyMutably(updates: any[], state: any): void {
7772
const models: T[] = []
7873

79-
const didMutateIds =
80-
updates.filter(update => takeUpdatedModel(models, update, state)).length >
81-
0
82-
83-
if (models.length === 0) {
84-
return DidMutate.None
85-
} else {
86-
const originalIds = state.ids
87-
const updatedIndexes: any[] = []
88-
state.ids = state.ids.filter((id: any, index: number) => {
89-
if (id in state.entities) {
90-
return true
91-
} else {
92-
updatedIndexes.push(index)
93-
return false
94-
}
95-
})
74+
updates.forEach(update => takeUpdatedModel(models, update, state))
9675

76+
if (models.length !== 0) {
9777
merge(models, state)
98-
99-
if (
100-
!didMutateIds &&
101-
updatedIndexes.every((i: number) => state.ids[i] === originalIds[i])
102-
) {
103-
return DidMutate.EntitiesOnly
104-
} else {
105-
return DidMutate.Both
106-
}
10778
}
10879
}
10980

110-
function mapMutably(map: EntityMap<T>, state: R): DidMutate
111-
function mapMutably(updatesOrMap: any, state: any): DidMutate {
81+
function mapMutably(map: EntityMap<T>, state: R): void
82+
function mapMutably(updatesOrMap: any, state: any): void {
11283
const updates: Update<T>[] = state.ids.reduce(
11384
(changes: any[], id: string | number) => {
11485
const change = updatesOrMap(state.entities[id])
@@ -120,16 +91,16 @@ export function createSortedStateAdapter<T>(selectId: any, sort: any): any {
12091
[]
12192
)
12293

123-
return updateManyMutably(updates, state)
94+
updateManyMutably(updates, state)
12495
}
12596

126-
function upsertOneMutably(entity: T, state: R): DidMutate
127-
function upsertOneMutably(entity: any, state: any): DidMutate {
97+
function upsertOneMutably(entity: T, state: R): void
98+
function upsertOneMutably(entity: any, state: any): void {
12899
return upsertManyMutably([entity], state)
129100
}
130101

131-
function upsertManyMutably(entities: T[], state: R): DidMutate
132-
function upsertManyMutably(entities: any[], state: any): DidMutate {
102+
function upsertManyMutably(entities: T[], state: R): void
103+
function upsertManyMutably(entities: any[], state: any): void {
133104
const added: any[] = []
134105
const updated: any[] = []
135106

@@ -142,54 +113,42 @@ export function createSortedStateAdapter<T>(selectId: any, sort: any): any {
142113
}
143114
}
144115

145-
const didMutateByUpdated = updateManyMutably(updated, state)
146-
const didMutateByAdded = addManyMutably(added, state)
147-
148-
switch (true) {
149-
case didMutateByAdded === DidMutate.None &&
150-
didMutateByUpdated === DidMutate.None:
151-
return DidMutate.None
152-
case didMutateByAdded === DidMutate.Both ||
153-
didMutateByUpdated === DidMutate.Both:
154-
return DidMutate.Both
155-
default:
156-
return DidMutate.EntitiesOnly
116+
updateManyMutably(updated, state)
117+
addManyMutably(added, state)
118+
}
119+
120+
function areArraysEqual(a: any[], b: any[]) {
121+
if (a.length !== b.length) {
122+
return false
123+
}
124+
125+
for (let i = 0; i < a.length && i < b.length; i++) {
126+
if (a[i] === b[i]) {
127+
continue
128+
}
129+
return false
157130
}
131+
return true
158132
}
159133

160134
function merge(models: T[], state: R): void
161135
function merge(models: any[], state: any): void {
162136
models.sort(sort)
163137

164-
const ids: any[] = []
138+
// Insert/overwrite all new/updated
139+
models.forEach(model => {
140+
state.entities[selectId(model)] = model
141+
})
165142

166-
let i = 0
167-
let j = 0
143+
const allEntities = Object.values(state.entities)
144+
allEntities.sort(sort)
168145

169-
while (i < models.length && j < state.ids.length) {
170-
const model = models[i]
171-
const modelId = selectIdValue(model, selectId)
172-
const entityId = state.ids[j]
173-
const entity = state.entities[entityId]
146+
const newSortedIds = allEntities.map(selectId)
147+
const { ids } = state
174148

175-
if (sort(model, entity) <= 0) {
176-
ids.push(modelId)
177-
i++
178-
} else {
179-
ids.push(entityId)
180-
j++
181-
}
149+
if (!areArraysEqual(ids, newSortedIds)) {
150+
state.ids = newSortedIds
182151
}
183-
184-
if (i < models.length) {
185-
state.ids = ids.concat(models.slice(i).map(selectId))
186-
} else {
187-
state.ids = ids.concat(state.ids.slice(j))
188-
}
189-
190-
models.forEach(model => {
191-
state.entities[selectId(model)] = model
192-
})
193152
}
194153

195154
return {

src/entities/state_adapter.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
11
import createNextState, { Draft } from 'immer'
22
import { EntityState } from './models'
33

4-
export enum DidMutate {
5-
EntitiesOnly,
6-
Both,
7-
None
8-
}
9-
104
export function createStateOperator<V, R>(
11-
mutator: (arg: R, state: EntityState<V>) => DidMutate
5+
mutator: (arg: R, state: EntityState<V>) => void
126
): EntityState<V>
137
export function createStateOperator<V, R>(
14-
mutator: (arg: any, state: any) => DidMutate
8+
mutator: (arg: any, state: any) => void
159
): any {
1610
return function operation<S extends EntityState<V>>(arg: R, state: any): S {
1711
// @ts-ignore createNextState() produces an Immutable<Draft<S>> rather
1812
// than an Immutable<S>, and TypeScript cannot find out how to reconcile
1913
// these two types.
2014
return createNextState(state, (draft: Draft<EntityState<V>>) => {
21-
const { ids: originalIds } = draft
22-
const didMutate = mutator(arg, draft)
23-
24-
if (didMutate === DidMutate.EntitiesOnly) {
25-
draft.ids = originalIds
26-
}
15+
mutator(arg, draft)
2716
})
2817
}
2918
}

0 commit comments

Comments
 (0)