如何使用 ImmutableJS 更新 List 中的多个元素?

How to update multiple element inside List with ImmutableJS?

您好,我正在使用 immutableJS,如果数组中的多个对象具有与 action.contacts

相同的 ID,我想更新它
const initialState = fromJS({
  list: [{
    id: 1,
    loading: false,
  }, {
    id: 2,
    loading: false,
  }, {
    id: 3,
    loading: false,
  }]
});

action.contacts = [{
  id: 1
}, {
  id: 2
}]

我预计当我调用 state.get('list') 时它会等于

  list: [{
    id: 1,
    loading: true,
  }, {
    id: 2,
    loading: true,
  }, {
    id: 3,
    loading: false,
  }]

到目前为止我所做的是:

case UNLOCK_CONTACTS:
    const indexesOfRow = state.get('list').findIndex((listItem) => {
      return action.contacts.map((contact)=> listItem.get('id') === contact.id)
    })

    return indexesOfRow.map((index)=> {
      state.setIn(['list', index, 'loading'], true);
    });
  }));

但它对我不起作用,没有更新任何东西

我在 fiddle http://jsfiddle.net/xxryan1234/djj6u8xL/398/

中创建了一个类似的解决方案

您错过了 immutable.js 的要点。对象不可变。

const initialState = Immutable.fromJS({
  list: [{
    id: 1,
    loading: false
    }, {
    id: 2,
    loading: false
    }, {
    id: 3,
    loading: false
    }],
});

const contacts = [{
    id: 1
}, {
    id: 3
}]


let newState = initialState.set( 'list', initialState.get('list').map( (row,index) => {

  let contact = contacts.find((item)=>{
    return item.id == row.get('id')
  })

  if (contact){
    return row.set('loading', true)
  }
  return row;
}))

console.log(newState.toJS())

请参阅更新后的 fiddle http://jsfiddle.net/djj6u8xL/399/

const newState = initialState.update('list', (oldValue) => 
                  oldValue.map(item => 
                    action.contacts.find(act => 
                      act.get('id') === item.get('id')) !== undefined ? 
                       item.update('loading',(oldVal)=> !oldVal) : item))
  console.log(newState.toJS())

注意:您需要将 action.contacts 变成不可变映射的不可变列表。

case UNLOCK_CONTACTS:
  return state.set('list', state.get('list').map((listItem) => {
    const matched = _.find(action.contacts, (contact) => listItem.get('id') === contact.id);
    if (matched) {
      return fromJS({ ...listItem.toJS(), loading: true });
    }
    return listItem;
  }));

所以我设法通过映射列表然后查找 listItem 是否存在于 action.contacts 中来解决它。如果它匹配我 return 与 loading: true 匹配的对象,如果不匹配我 return 相同的对象。

我乐于接受如何重构此解决方案的建议,我对不可变 js 很陌生,我觉得有更简单的方法来解决这个问题,但我还不知道。