Skip to content

Commit

Permalink
Core Data: Add util for minimally modifying items. (#16823)
Browse files Browse the repository at this point in the history
  • Loading branch information
epiqueras authored Jul 30, 2019
1 parent 208ff09 commit 823ba36
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
37 changes: 37 additions & 0 deletions packages/core-data/src/utils/conservative-map-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* External dependencies
*/
import { isEqual } from 'lodash';

/**
* Given the current and next item entity, returns the minimally "modified"
* result of the next item, preferring value references from the original item
* if equal. If all values match, the original item is returned.
*
* @param {Object} item Original item.
* @param {Object} nextItem Next item.
*
* @return {Object} Minimally modified merged item.
*/
export default function conservativeMapItem( item, nextItem ) {
// Return next item in its entirety if there is no original item.
if ( ! item ) {
return nextItem;
}

let hasChanges = false;
const result = {};
for ( const key in nextItem ) {
if ( isEqual( item[ key ], nextItem[ key ] ) ) {
result[ key ] = item[ key ];
} else {
hasChanges = true;
result[ key ] = nextItem[ key ];
}
}

if ( ! hasChanges ) {
return item;
}
return result;
}
1 change: 1 addition & 0 deletions packages/core-data/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as conservativeMapItem } from './conservative-map-item';
export { default as ifMatchingAction } from './if-matching-action';
export { default as onSubKey } from './on-sub-key';
export { default as replaceAction } from './replace-action';
Expand Down
33 changes: 33 additions & 0 deletions packages/core-data/src/utils/test/conservative-map-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Internal dependencies
*/
import conservativeMapItem from '../conservative-map-item';

describe( 'conservativeMapItem', () => {
it( 'Returns the next item if there is no current item to compare with.', () => {
const item = undefined;
const nextItem = {};
const result = conservativeMapItem( item, nextItem );

expect( result ).toBe( nextItem );
} );

it( 'Returns the original item if all property values are the same, deeply.', () => {
const item = { a: [ {} ] };
const nextItem = { a: [ {} ] };
const result = conservativeMapItem( item, nextItem );

expect( result ).toBe( item );
} );

it( 'Preserves original references of property values when unchanged, deeply.', () => {
const item = { a: [ {} ], b: [ 1 ] };
const nextItem = { a: [ {} ], b: [ 2 ] };
const result = conservativeMapItem( item, nextItem );

expect( result ).not.toBe( item );
expect( result.a ).toBe( item.a );
expect( result.b ).toBe( nextItem.b );
expect( result ).toEqual( { a: [ {} ], b: [ 2 ] } );
} );
} );

0 comments on commit 823ba36

Please sign in to comment.