2016-02-11 7 views
13

Есть ли элегантный способ удаления объекта из массива, который является частью массива? Я работаю с React и Redux какое-то время, но застрял несколько часов каждый раз, когда мне приходится удалять или вставлять данные, не изменяя состояние.Удалить данные из вложенных объектов без мутирования

Редуктор представляет собой массив, содержащий объекты, которые имеют идентификатор и другой массив с объектами, например:

[ 
{ id:123, 
    items:[ 
      { id: abc, 
      name: albert 
      }, 
      ... 
     ] 
}, 
... 
] 

я получаю как идентификаторы и нужно удалить элемент с ID abc.

+1

Вы должны прочитать этот и пересмотреть вашу государственную структуру. http://stackoverflow.com/questions/32135779/updating-nested-data-in-redux-store/32921731#32921731 – larrydahooster

+0

Вместо того, чтобы передать полный комплексный массив редуктору, создайте новый редуктор, который получает элемент массива как государство, чтобы внести изменения –

+0

Ну, это также способ сделать это. Но чем каждый раз мне нужны элементы объекта с id: 123, я должен «искать» для них. И еще один вопрос, когда я получаю JSON, как это из бэкэнд, как я разделить его на несколько редукторов? Выборка осуществляется посредством действия, которое идет на один редуктор. –

ответ

28

Чтобы удалить элемент из массива по идентификатору:

return state.filter(item => item.id !== action.id) 

Чтобы удалить ключ из объекта по ID:

let copy = Object.assign({}, state) // assuming you use Object.assign() polyfill! 
delete copy[action.id] // shallowly mutating a shallow copy is fine 
return copy 

(Bonus) То же самое с object spread operator proposal:

let { [action.id]: deletedItem, ...rest } = state 
return rest 
+0

Сочетание того, что я в конечном итоге использовал. –

+0

Что означает 'deletedItem' do/mean/содержать в последнем примере? – Mbrevda

+0

@Mbrevda 'deletedItem' - это просто имя переменной, которому назначен элемент, который был удален (элемент, присвоенный' action.id'). Вы превращаете свое состояние в два новых объекта, у которых есть отклоненный элемент, а другой - с остальными. –

0

Вы можете использовать Underscore's reject. Он делает именно то, что вы пытаетесь сделать.

+0

Он возвращает массив не объект. – Sassan

0

Если вы решите простой Javascript, самый элегантный способ, которым я могу думать о том, чтобы использовать Array.prototype.reduce уменьшить состояние:

var state = [ 
{ id: 123, 
    items:[ 
      { id: 'abc', 
      name: 'albert' 
      }, 
      ... 
     ] 
}, 
... 
] 

function filterOut (state) { 
    return (bucketId, personId) => { 
    return state.reduce((state, bucket) => { 
     return state.concat(
     (bucketId === bucket.id) ? 
      Object.assign({}, bucket, {items: bucket.items.filter((person) => person.id !== personId)}) : 
      bucket 
    ); 
    }, []); 
    } 
} 

var newState = filterOut(state)(123, 'abc'); 
0

Вы также можете использовать lodash's omit method.

Имейте в виду, что импорт lodash значительно увеличит ваш размер сборки. Держите его под контролем только путем импорта только определенного метода: import omit from 'lodash/omit';

Если возможно, я предлагаю использовать оператор разнесения объектов, как описано в Dan's answer.

0

я решить мою проблему таким образом

if(action.type === "REMOVE_FROM_PLAYLIST"){ 
     let copy = Object.assign({}, state) 
     delete copy.playlist[action.index].songs[action.indexSongs]; 

     return copy; 
    } 

надеюсь, что это помогает кто-либо другой.

2
const remove = (state, bucketId, personId) => state.map(
    bucket => bucket.id === bucketId 
    ? { ...bucket, items: bucket.items.filter(person => person.id !== personId) } 
    : bucket, 
); 

Использование:

const state = [ 
    { 
    id: 123, 
    items: [ 
     { 
     id: 'abc', 
     name: 'Kinna', 
     }, 
     { 
     id: 'def', 
     name: 'Meggy', 
     }, 
    ], 
    }, 
    { 
    id: 456, 
    items: [ 
     { 
     id: 'ghi', 
     name: 'Ade', 
     }, 
     { 
     id: 'jkl', 
     name: 'Tades', 
     }, 
    ], 
    }, 
]; 

console.log(remove(state, 123, 'abc')); 
Смежные вопросы