11import isNil from 'lodash.isnil'
22
3+ const CUSTOM = 'custom'
4+
35/**
46 * @function copyEmptyArrayProps
5- * @description Takes two objects and if there are Array props in oldObj which doesn't exist in newObj, then copy it with an empty value.
7+ * @description Create new key with empty array value on `newobj` for the arrays exist on `oldObj` and doesnt exist on `newobj`
8+ * One use case is to easily compare two object without generating this error `Cannot read property '0' of undefined`
69 * @param {Object } oldObj
710 * @param {Object } newObj
811 * @returns {Array } Ordered Array [oldObj, newObj]
@@ -15,13 +18,49 @@ export default function copyEmptyArrayProps(oldObj = {}, newObj = {}) {
1518 ...newObj ,
1619 ...nextObject ,
1720 }
21+
22+ // Ignore CUSTOM key as this object is dynamic and its up to the user to dynamically change it
23+ // todo, it would be better if we pass it as ignored keys param
24+ if ( key === CUSTOM ) return merged
25+
26+ if ( Array . isArray ( value ) && newObj [ key ] && newObj [ key ] . length >= 1 ) {
27+ /* eslint-disable no-plusplus */
28+ for ( let i = 0 ; i < newObj [ key ] . length ; i ++ ) {
29+ if (
30+ ! isNil ( newObj [ key ] [ i ] ) &&
31+ typeof newObj [ key ] [ i ] === 'object' &&
32+ ! isNil ( newObj [ key ] [ i ] . id )
33+ ) {
34+ // Since its unordered array elements then check if the element on `oldObj` exists by id
35+ const foundObject = value . find (
36+ ( v ) => Number ( v . id ) === Number ( newObj [ key ] [ i ] . id )
37+ )
38+ if ( ! isNil ( foundObject ) ) {
39+ const [ , nestedObject ] = copyEmptyArrayProps (
40+ foundObject ,
41+ newObj [ key ] [ i ]
42+ )
43+ /* eslint-disable no-param-reassign */
44+ newObj [ key ] [ i ] = nestedObject
45+ }
46+ }
47+ }
48+
49+ return merged
50+ }
1851 if ( Array . isArray ( value ) ) {
1952 return {
2053 ...merged ,
2154 [ key ] : isNil ( newObj [ key ] ) ? [ ] : newObj [ key ] ,
2255 }
2356 }
24- if ( ! isNil ( newObj [ key ] ) && typeof value === 'object' ) {
57+ if (
58+ ! isNil ( newObj [ key ] ) &&
59+ typeof value === 'object' &&
60+ // Ignore Date as this will create invalid object since typeof date === 'object' return true
61+ // ex: {date: new Date()} will result {date: {}}
62+ ! ( value instanceof Date )
63+ ) {
2564 const [ , nestedObject ] = copyEmptyArrayProps ( value , newObj [ key ] )
2665 return {
2766 ...merged ,
0 commit comments