Удаление элемента из массива в состоянии компонента
Я пытаюсь найти лучший способ удалить элемент из массива в состоянии компонента. Поскольку я не должен изменять this.state
переменная напрямую, есть ли лучший способ (более сжатый) удалить элемент из массива, чем то, что у меня здесь?:
onRemovePerson: function(index) {
this.setState(prevState => { // pass callback in setState to avoid race condition
let newData = prevState.data.slice() //copy array from prevState
newData.splice(index, 1) // remove element
return {data: newData} // update state
})
},
спасибо.
обновлено
это было обновлено для использования обратного вызова в setState. Это должно быть сделано при ссылке на текущее состояние при его обновлении.
9 ответов
самый чистый способ сделать это, что я видел с filter
:
removeItem(index) {
this.setState({
data: this.state.data.filter((_, i) => i !== index)
});
}
можно использовать update()
помощник неизменности от react-addons-update
, которая эффективно делает то же самое под капотом, но то, что вы делаете хорошо.
this.setState(prevState => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
Я считаю, что ссылка this.state
внутри setState()
обескураживают
https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
врачи рекомендуют использовать setState()
С функцией обратного вызова, так что prevState передается во время выполнения, когда происходит обновление. Так вот как это будет выглядеть:
Используя Массив.прототип.фильтр без ES6
removeItem : function(index) {
this.setState(function(prevState){
return { data : prevState.data.filter(function(val, i) {
return i !== index;
})};
});
}
используя Матрица.прототип.фильтр с функциями стрелки ES6
removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i !== index)
}));
}
использование неизменяемости-helper
import update from 'immutability-helper'
...
removeItem(index) {
this.setState((prevState) => ({
data: update(prevState.data, {$splice: [[index, 1]]})
}))
}
Использование Spread
function removeItem(index) {
this.setState((prevState) => ({
data: [...prevState.data.slice(0,index), ...prevState.data.slice(index+1)]
}))
}
обратите внимание, что в каждом случае, независимо от используемой техники,this.setState()
передается обратный вызов, а не Ссылка на объект старый this.state
;
вот способ удалить элемент из массива в состоянии с помощью синтаксиса распространения ES6.
onRemovePerson: (index) => {
const data = this.state.data;
this.setState({
data: [...data.slice(0,index), ...data.slice(index+1)]
});
}
Как упоминалось в комментарии к ответу эфриона выше, filter () может быть медленным, особенно с большими массивами, поскольку он циклически ищет индекс, который, похоже, уже определен. Это чистое, но неэффективное решение.
в качестве альтернативы можно просто "вырезать" нужный элемент и объединить фрагменты.
var dummayArray = [];
this.setState({data:dummyArray.concat(this.state.data.slice(0,index),this.state.data.slice(index))})
надеюсь, что это помогает!
вы можете использовать эту функцию, если вы хотите удалить элемент (без индекса)
removeItem(item) {
this.setState(prevState => {
data: prevState.data.filter(i => i !== item)
});
}
Я хочу перезвонить здесь, хотя этот вопрос уже был правильно ответил @pscl в случае, если кто-то еще столкнется с той же проблемой, что и я. Из 4 методов я решил использовать синтаксис es6 с функциями стрелки из-за его краткости и отсутствия зависимости от внешних библиотек:
Используя Массив.прототип.фильтр с функциями стрелки ES6
removeItem(index) {
this.setState((prevState) => ({
data: prevState.data.filter((_, i) => i != index)
}));
}
как вы можете видеть, я сделал небольшое изменение, чтобы игнорировать тип индекса (!==
to !=
) потому что в моем случае я получал индекс из строкового поля.
еще один полезный момент, если вы видите странное поведение при удалении элемента на стороне клиента-это никогда не используйте индекс массива в качестве ключа для элемента:
// bad
{content.map((content, index) =>
<p key={index}>{content.Content}</p>
)}
когда React отличается от виртуального DOM при изменении, он будет смотреть на ключи, чтобы определить, что изменилось. Поэтому, если вы используете индексы, и в массив, он удалит последний. Вместо этого используйте идентификаторы содержимого в качестве ключей, например.
// good
{content.map(content =>
<p key={content.id}>{content.Content}</p>
)}
приведенная выше выдержка из этот ответ из поста.
Счастливое Кодирование Всех!
Я использую это, надеюсь, что у него нет проблем и помощи.
removeItem(item){
const index = this.state.yourArray.indexOf(item);
if (index < 0 ) return
this.state.yourArray.splice(index, 1)
this.setState({yourArray: this.state.yourArray})
}
вот простой способ сделать это:
removeFunction(key){
const data = {...this.state.data}; //Duplicate state.
delete data[key]; //remove Item form stateCopy.
this.setState({data}); //Set state as the modify one.
}
надеюсь, это поможет!!!