Как отредактировать элемент в массиве состояний?

Итак, вот мое состояние:

this.state = {
  ids: ['A', 'E', 'C']
};

Как мне изменить модификацию состояния, чтобы "E" в индексе 1 был изменен на "B"? Как например:

this.setState({
  ids[1]: 'B'
});

Как это сделать?

Ответ 1

Мое предложение состоит в том, чтобы привыкнуть использовать неизменяемые операции, чтобы не изменять объект внутреннего состояния.

Как указано в справочной документации:

Никогда не изменяйте this.state напрямую, так как впоследствии вызов setState() может заменить сделанную вами мутацию. Относитесь к этому состоянию как к неизменному.

В этом случае вы можете [1] использовать slice() чтобы получить новую копию массива, [2] манипулировать копией, а затем [3] setState с новым массивом. Это хорошая практика.

Что-то вроде того:

const newIds = this.state.ids.slice() //copy the array
newIds[1] = 'B' //execute the manipulations
this.setState({ids: newIds}) //set the new state

Ответ 2

Случай 1: Если вы знаете индекс, вы можете написать его так:

let ids = [...this.state.ids];     // create the copy of state array
ids[index] = 'k';                  //new value
this.setState({ ids });            //update the value

Случай 2: если вы не знаете индекс, то сначала используйте array.findIndex или любой другой цикл, чтобы получить индекс элемента, который вы хотите обновить, после этого обновите значение и используйте setState.

Как это:

let ids = [...this.state.ids];  
let index = ids.findIndex(el => /* condition */);
ids[index] = 'k';                  
this.setState({ ids });            

Ответ 3

Основываясь на том, что написал @mayank-shukla (случай 2: зная индекс элемента для замены), это также можно записать с помощью Array.splice:

const replacement = 'B';
let copy = [...this.state.ids]
copy.splice(index, 1, replacement)

this.setState({ 
   ids: copy,
})

Пример REPL

Здесь следует отметить две вещи:

  1. Array.splice является мутативным; Это изменит массив, на котором он работает, но это мелкая копия массива из-за оператора распространения. Подробнее об этом ниже.
  2. Вы не можете напрямую назначить результат сращивания, так как возвращаемое значение Array.splice фактически является удаленным элементом (ами). AKA: Не присваивайте результат вашего среза переменной, которую вы намереваетесь присвоить идентификаторам в setState, иначе у вас останутся только удаленные значения.

Чтобы продолжить изучение мелких и глубоких копий из пункта 1, обратите внимание, что если вы заменяете ссылки на объекты (вместо строковых литералов в вопросе), вам необходимо использовать что-то вроде lodash cloneDeep.

Хотя есть несколько других способов обойти это.

Вы также можете прочитать больше о мелком и глубоком на самом SO.

Ответ 4

Вот еще одно решение для изменения определенного индекса массива в setState:

this.setState({
  ...array,
  Object.assign([...array], { [id]: yourNewObjectOrValue })
})