3

I need to update some keys of a nested object, but whether or not each key is updated comes with some if condition.

Currently I am using lodash cloneDeep() like below ... which works fine, but I want to improve on performance so i want to use immutability-helper library instead.

    state = {
        info : {
            xyz : {
                name : {
                    first : '',
                    last : '',
                },
                age : '',
            }
        }
    }
    
    let newInfo = _.cloneDeep(this.state.info);
    if (some condition)
        newInfo.xyz.name.first = 'iron'
    if (some condition)
        newInfo.xyz.name.last = 'man'
    if (some condition)
        newInfo.xyz.age = 50
    
    this.setState({ info : newInfo});

But the problem is that the immutability helper sort of requires all changes in one update call. So either i put all these if conditions inside the update call. I dont even know how to do that, and even if i do, that will make the code very unreadable if i have many conditions and many keys to update.

Or create multiple copies (1 for each change) and merge them later somehow ???

    import update from 'immutability-helper';

    if (some condition)
        newInfo_1 = update(this.state.info, {xyz: {name: {first: {$set: 'iron' }}}} )
    if (some condition)
        newInfo_2 = update(this.state.info, {xyz: {name: {last: {$set: 'man' }}}} )
    if (some condition)
        newInfo_3 = update(this.state.info, {xyz: {age: {$set: 50 }}} )

    // do i merge the newInfo_1, _2 & _3 somehow ???? 
    // this.setState({ info : ????? })

Is there a correct way to do conditional updates with immutability-helper ?

kernelman
  • 992
  • 1
  • 13
  • 28

1 Answers1

3

You can use the $apply command to conditionally apply changes. It takes a function as argument, and passes the current value to the function. So, you could do something like this:

const condition1 = true;
const condition2 = true;
const condition3 = false;

const updatedInfo = update(this.state.info, {
  xyz: {
    name: {
      first: {
        $apply: current => condition1 ? 'iron' : current 
      },
      last: {
        $apply: current => condition2 ? 'man' : current 
      }
    },
    age: {
      $apply: current => condition3 ? 50 : current 
    }
  }
})

The command also comes with a shorthand, so you can pass the function directly, like this:

first: current => condition1 ? "iron" : current,
Riwen
  • 4,734
  • 2
  • 19
  • 31