2016-08-02 5 views
3

Как изменить свойство объекта в ImmutableList({}), который находится внутри Immutable.Map({})?Как изменить свойство объекта в ImmutableList ({}) внутри Immutable.Map ({})

у меня есть:

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 в списке. Затем измените его свойство на true. Я также хочу, чтобы свойство active было false для всех остальных элементов в списке.

Как это сделать? Заранее большое спасибо.

Edit (окончательное решение):

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 
     }); 
    }; 
} 
+0

что вы имеете в виду изменения непреложный? дело в том, что вы не можете; вы должны дублировать и объединять ... – dandavis

+0

Я хочу вернуть новую неизменяемую карту с новыми значениями. – Michal

+0

Как его дублировать и объединить? Не могли бы вы показать мне пример? Это именно то, что я ищу. – Michal

ответ

2

Вы можете перемещаться по неизменному, как это (быстрая заметка, хотя я очень рекомендую вам сделать enti re объект неизменный). Вы можете держать вниз строки кода и держать его немного более элегантно по только используя неизменен сам -

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); 
     } 
    }) 
) 

Смотреть рабочую скрипку - https://jsfiddle.net/o04btr3j/214/

Это обновляет ключ list внутри объекта (если это не существует по какой-либо причине по умолчанию для неизменяемого списка), а затем отображает свойства. Если он имеет идентификатор 1, он будет активным, если в противном случае он будет активным, чтобы установить значение 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/независимо.

0

Что следует должно работать, но, как кто-то сказал ... Я думаю, что может быть лучше полное обновление ...

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>

+0

Это выглядит великолепно. Я получаю сообщение об ошибке: 'Uncaught TypeError: k не является функцией' – Michal

+0

Я сделал редактирование ... – Hitmands

+0

, но кто-то любит downvoting ... его можно принять? – Hitmands

1

Я создал податливое пример на 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()) 
+0

Спасибо за ваше время. Я только что принял ответ аджмаймаймы. – Michal