Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core Data: Add util for minimally modifying items. #16823

Merged
merged 1 commit into from
Jul 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ] } );
} );
} );