Удаление элемента из массива в состоянии компонента

Я пытаюсь найти лучший способ удалить элемент из массива в состоянии компонента. Поскольку я не должен изменять 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.
}

надеюсь, это поможет!!!