import isEqual from 'lodash/isEqual';
/**
* @module util/assignIfChanged
*/
/**
* Merges the properties of `newProps` into `target`, like Object.assign. However, each property
* is compared with the existing property on the `target` object. If the properties are equal, the
* property on the `target` object will not be overwritten.
*
* _note: This logic is applied for each top-level property of `newProps`, but not for deeply
* nested properties. _
*
* This util is useful when we want to cause as little mutations to the target object as possible.
* For example, in reducers mutations to objects will generally cause attached selectors and React
* components to update.
*
* @param target {Object} The object to update properties on
* @param newProps {Object} An object containing new properties
* @param compare {function} The function that will be used to compare properties from newProps
* to existing properties on target. Defaults to the
* {@link https://lodash.com/docs/4.17.4#isEqual|lodash isEqual} util.
* @returns {Object} A new object with the changed properties from newProps. If no properties have
* changed, will return a reference to the original object.
*/
function assignIfChanged(target, newProps, compare = isEqual) {
const result = { ...target };
let hasChange = false;
Object.keys(newProps).forEach(newKey => {
if (!compare(result[newKey], newProps[newKey])) {
hasChange = true;
result[newKey] = newProps[newKey];
}
});
return hasChange ? result : target;
}
export default assignIfChanged;