1

I'm currently working on a project with react and I'm facing a problem in merging two objects when using setState method. I have two objects similar to

person1 = {
    name: 'ramya',
    age: 21,
    gender: 'f',
    skills:{
        technicalSkills: {
            languages: ['C', 'C++', 'Java'],
            operatingSystems: ['Unix', 'Linux']
        },
        linguisticSkills: {
            toSpeak: ['English', 'Tamil'],
            toRead: ['English']
        }
    },
}

obj2 = {
    skills: {
        linguisticSkills: {
            toRead: ['English', 'Tamil']
        }
    }
}

I want to change state of person 1's skills.linguisticSkills to

linguisticSkills: {
                toSpeak: ['English', 'Tamil'],
                toRead: ['English', 'Tamil']
} 

skills.linguisticSkills.toSpeak and skills.linguisticSkills.toRead keep changing i.e items are added or removed. Whenever it is changes how do I merge person1 and obj2 in setState so I end up in the right state?

UPDATE: _.merge fails for a case like this:

person1 = {
        name: 'ramya',
        age: 21,
        gender: 'f',
        skills:{
            technicalSkills: {
                languages: ['C', 'C++', 'Java'],
                operatingSystems: ['Unix', 'Linux']
            },
            linguisticSkills: {
                toSpeak: ['English', 'Tamil'],
                toRead: ['English', 'Tamil', 'Telugu']
            }
        },
    }

    obj2 = {
        skills: {
            linguisticSkills: {
                toRead: ['English', 'Tamil']
            }
        }
    }

It gives the result same as person 1 whereas

{
        name: 'ramya',
        age: 21,
        gender: 'f',
        skills:{
            technicalSkills: {
                languages: ['C', 'C++', 'Java'],
                operatingSystems: ['Unix', 'Linux']
            },
            linguisticSkills: {
                toSpeak: ['English', 'Tamil'],
                toRead: ['English', 'Tamil']
            }
        },
    }

is expected.

0

2 Answers 2

11

Lodash's _.merge() is recursive. If you need more granular control about the merge process, you can use _.mergeWith().

const person1 = {"name":"ramya","age":21,"gender":"f","skills":{"technicalSkills":{"languages":["C","C++","Java"],"operatingSystems":["Unix","Linux"]},"linguisticSkills":{"toSpeak":["English","Tamil"],"toRead":['English', 'Tamil', 'Telugu']}}}

const obj2 = {"skills":{"linguisticSkills":{"toRead":["English","Tamil"]}}}

const result = _.mergeWith({}, person1, obj2, (objValue, srcValue) => {
  if( _.isArray(srcValue)) {
    return srcValue;
  }
});

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

4

check out https:How to deep merge instead of shallow merge?

/**
 * Simple object check.
 * @param item
 * @returns {boolean}
 */
export function isObject(item) {
  return (item && typeof item === 'object' && !Array.isArray(item));
}

/**
 * Deep merge two objects.
 * @param target
 * @param ...sources
 */
export function mergeDeep(target, ...sources) {
  if (!sources.length) return target;
  const source = sources.shift();

  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        mergeDeep(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }

  return mergeDeep(target, ...sources);
}

// Code copied from linked Stack Overflow question
// https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge
// Answer by Salakar:
// https://stackoverflow.com/users/2938161/salakar

2 Comments

Yea I tried something similar and bam, it worked ! Thanks a lot
I used _.extend as posted in one of the answers to the question in the link you gave

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.