如何在 Immutable.Map({}) 内更改 ImmutableList({}) 中项目的 属性

How to change property of item in ImmutableList({}) inside Immutable.Map({})

如何更改 Immutable.Map({})ImmutableList({}) 中项目的 属性?

我有:

const initialState = Immutable.Map({
    width: window.board.width,
    height: window.board.height,
    lines: Immutable.List([
        Immutable.Map({id: 1, active: false, name: 'Some name'}),
        Immutable.Map({id: 2, active: false, name: 'Sad name'}),
        Immutable.Map({id: 3, active: true, name: 'Cool name'})
    ])
});

假设我想在列表中设置 id 1 的项目。然后将其 属性 active 更改为 true。我还想将列表中所有其他项目的 属性 active 设置为 false。

我该怎么做?提前致谢。

编辑(最终解决方案):

export function activateLine(lineId) {
    return function (dispatch, getState) {
        const updatedLines = getState().board.update('lines', Immutable.List(),
            (oldList) => oldList.map((listItem) => {
                return listItem.set("active", (listItem.get("id") === lineId));
            })).get('lines');

        return dispatch({
            type: types.ACTIVATE_LINE,
            payload: updatedLines
        });
    };
}

接下来的内容应该可行,但是,正如有人所说...我认为完整更新可能会更好...

const initialState = Immutable.Map({
    lines: Immutable.List([
        Immutable.Map({id: 1, active: false, name: 'Some name'}),
        Immutable.Map({id: 2, active: false, name: 'Sad name'}),
        Immutable.Map({id: 3, active: true, name: 'Cool name'})
    ])
});

let lines = initialState.get('lines'); 
let id = 1; // what you want update...
let updater = item => {
  let updated = item.set('name', "Giuseppe");
  
  return updated;
};
let index = lines.findIndex((i) => i.get("id") === id);
let result = lines.update(index, updater);

initialState.set("lines", result);
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.1/immutable.js"></script>

您可以像这样遍历不可变对象(请注意,尽管我强烈建议您将整个对象设置为不可变对象)。您可以通过 just 使用不可变本身来减少代码行并使其更优雅 -

const changeImmutableObject = initialState.update('lines', Immutable.List(),
    (oldList) => oldList.map((listItem) => {
        if(listItem.get("id") === 1) {
            return listItem.set("active", true);
        } else {
            return listItem.set("active", false);
        }
    })
  )

查看工作 fiddle - https://jsfiddle.net/o04btr3j/214/

这会更新对象内的 list 键(如果它由于某种原因不存在,则默认为不可变列表),然后映射到属性上。如果它的 id 为 1,它会将 active 设置为 true,否则它会将 active 设置为 false。

您也可以只 initialState.toJS() 您的不可变对象并在纯 js 中执行您的逻辑,或者执行和 immutableobject.get('property') 并修改然后将其设置回您的对象,但是我建议您只是使用不可变的内置方法,因为它 代码少得多

此外,如果我没记错的话,你可以这样做:

const initialState = Immutable.fromJS({
width: window.board.width,
height: window.board.height,
lines:[
    {id: 1, active: false, name: 'Some name'},
    {id: 2, active: false, name: 'Sad name'},
    {id: 3, active: true, name: 'Cool name'}
]
});

你可以 immutable.fromJS() 一个对象,把它变成一个不可变的对象。所有不可变对象都应该有一个 .toJS 方法来将它们变回常规 javascript objects/lists/whatever.

我在 link to solution on jsbin.com

上创建了轻巧的示例
const initialState = Immutable.Map({
    lines: Immutable.List([
        Immutable.Map({id: 1, active: false, name: 'Some name'}),
        Immutable.Map({id: 2, active: false, name: 'Sad name'}),
        Immutable.Map({id: 3, active: true, name: 'Cool name'})
    ])
});


console.log('initialState', initialState.toJS())

// update lines, map over items and set active to false
const stateLinesAllNotActive = initialState.updateIn(
  ['lines'], 
  items => items.map((item) => item.set('active', false)) 
)

console.log('stateLinesAllNotActive', stateLinesAllNotActive.toJS())

// lines and key for item with id === 1, then set active to this item
const stateFirstActive = stateLinesAllNotActive.updateIn(
  [
    'lines', 
    stateLinesAllNotActive.get('lines').findIndex((item) => (item.get("id") === 1))
  ],
  item => item.set("active", true)
)

console.log('stateFirstActive', stateFirstActive.toJS())