Skip to content

Commit

Permalink
fix(Entity): Return a referentially equal state if state did not change
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeRyanDev committed Aug 18, 2017
1 parent 335d255 commit fbd6a66
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 37 deletions.
4 changes: 2 additions & 2 deletions modules/entity/spec/sorted_state_adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Sorted State Adapter', () => {

const readded = adapter.addOne(TheGreatGatsby, withOneEntity);

expect(readded).toEqual(withOneEntity);
expect(readded).toBe(withOneEntity);
});

it('should let you add many entities to the state', () => {
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('Sorted State Adapter', () => {
state
);

expect(withUpdates).toEqual(state);
expect(withUpdates).toBe(state);
});

it('should let you update the id of entity', () => {
Expand Down
4 changes: 2 additions & 2 deletions modules/entity/spec/unsorted_state_adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('Unsorted State Adapter', () => {

const readded = adapter.addOne(TheGreatGatsby, withOneEntity);

expect(readded).toEqual(withOneEntity);
expect(readded).toBe(withOneEntity);
});

it('should let you add many entities to the state', () => {
Expand Down Expand Up @@ -149,7 +149,7 @@ describe('Unsorted State Adapter', () => {
state
);

expect(withUpdates).toEqual(state);
expect(withUpdates).toBe(state);
});

it('should let you update the id of entity', () => {
Expand Down
43 changes: 28 additions & 15 deletions modules/entity/src/sorted_state_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,31 @@ export function createSortedStateAdapter<T>(
selectId
);

function addOneMutably(entity: T, state: R): void {
function addOneMutably(entity: T, state: R): boolean {
const key = selectId(entity);
const index = state.ids.indexOf(key);

if (index !== -1) {
return;
if (key in state.entities) {
return false;
}

const insertAt = findTargetIndex(state, entity);
state.ids.splice(insertAt, 0, key);
state.entities[key] = entity;

return true;
}

function addManyMutably(newModels: T[], state: R): void {
function addManyMutably(newModels: T[], state: R): boolean {
let didMutate = false;

for (let index in newModels) {
addOneMutably(newModels[index], state);
didMutate = addOneMutably(newModels[index], state) || didMutate;
}

return didMutate;
}

function addAllMutably(models: T[], state: R): void {
function addAllMutably(models: T[], state: R): boolean {
const sortedModels = models.sort(sort);

state.entities = {};
Expand All @@ -47,13 +52,13 @@ export function createSortedStateAdapter<T>(
state.entities[id] = model;
return id;
});
}

function updateOneMutably(update: Update<T>, state: R): void {
const index = state.ids.indexOf(update.id);
return true;
}

if (index === -1) {
return;
function updateOneMutably(update: Update<T>, state: R): boolean {
if (!(update.id in state.entities)) {
return false;
}

const original = state.entities[update.id];
Expand All @@ -64,14 +69,16 @@ export function createSortedStateAdapter<T>(
if (result === 0) {
if (updatedKey !== update.id) {
delete state.entities[update.id];
const index = state.ids.indexOf(update.id);
state.ids[index] = updatedKey;
}

state.entities[updatedKey] = updated;

return;
return true;
}

const index = state.ids.indexOf(update.id);
state.ids.splice(index, 1);
state.ids.splice(findTargetIndex(state, updated), 0, updatedKey);

Expand All @@ -80,12 +87,18 @@ export function createSortedStateAdapter<T>(
}

state.entities[updatedKey] = updated;

return true;
}

function updateManyMutably(updates: Update<T>[], state: R): void {
function updateManyMutably(updates: Update<T>[], state: R): boolean {
let didMutate = false;

for (let index in updates) {
updateOneMutably(updates[index], state);
didMutate = updateOneMutably(updates[index], state) || didMutate;
}

return didMutate;
}

function findTargetIndex(state: R, model: T) {
Expand Down
10 changes: 7 additions & 3 deletions modules/entity/src/state_adapter.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { EntityState, EntityStateAdapter } from './models';

export function createStateOperator<V, R>(
mutator: (arg: R, state: EntityState<V>) => void
mutator: (arg: R, state: EntityState<V>) => boolean
) {
return function operation<S extends EntityState<V>>(arg: R, state: S): S {
const clonedEntityState: EntityState<V> = {
ids: [...state.ids],
entities: { ...state.entities },
};

mutator(arg, clonedEntityState);
const didMutate = mutator(arg, clonedEntityState);

return Object.assign({}, state, clonedEntityState);
if (didMutate) {
return Object.assign({}, state, clonedEntityState);
}

return state;
};
}
49 changes: 34 additions & 15 deletions modules/entity/src/unsorted_state_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,59 @@ export function createUnsortedStateAdapter<T>(
): EntityStateAdapter<T> {
type R = EntityState<T>;

function addOneMutably(entity: T, state: R): void {
function addOneMutably(entity: T, state: R): boolean {
const key = selectId(entity);
const index = state.ids.indexOf(key);

if (index !== -1) {
return;
if (key in state.entities) {
return false;
}

state.ids.push(key);
state.entities[key] = entity;

return true;
}

function addManyMutably(entities: T[], state: R): void {
function addManyMutably(entities: T[], state: R): boolean {
let didMutate = false;

for (let index in entities) {
addOneMutably(entities[index], state);
didMutate = addOneMutably(entities[index], state) || didMutate;
}

return didMutate;
}

function addAllMutably(entities: T[], state: R): void {
function addAllMutably(entities: T[], state: R): boolean {
state.ids = [];
state.entities = {};

addManyMutably(entities, state);

return true;
}

function removeOneMutably(key: string, state: R): void {
function removeOneMutably(key: string, state: R): boolean {
const index = state.ids.indexOf(key);

if (index === -1) {
return;
return false;
}

state.ids.splice(index, 1);
delete state.entities[key];

return true;
}

function removeManyMutably(keys: string[], state: R): void {
function removeManyMutably(keys: string[], state: R): boolean {
let didMutate = false;

for (let index in keys) {
removeOneMutably(keys[index], state);
didMutate = removeOneMutably(keys[index], state) || didMutate;
}

return didMutate;
}

function removeAll<S extends R>(state: S): S {
Expand All @@ -55,11 +68,11 @@ export function createUnsortedStateAdapter<T>(
});
}

function updateOneMutably(update: Update<T>, state: R): void {
function updateOneMutably(update: Update<T>, state: R): boolean {
const index = state.ids.indexOf(update.id);

if (index === -1) {
return;
return false;
}

const original = state.entities[update.id];
Expand All @@ -72,12 +85,18 @@ export function createUnsortedStateAdapter<T>(
}

state.entities[newKey] = updated;

return true;
}

function updateManyMutably(updates: Update<T>[], state: R): void {
function updateManyMutably(updates: Update<T>[], state: R): boolean {
let didMutate = false;

for (let index in updates) {
updateOneMutably(updates[index], state);
didMutate = updateOneMutably(updates[index], state) || didMutate;
}

return didMutate;
}

return {
Expand Down

0 comments on commit fbd6a66

Please sign in to comment.