Подтвердить что ты не робот

React JS: как правильно удалить элемент из this.state.data, где data является массивом объектов

У меня есть компонент, который генерирует таблицу с строками данных (<tr> и т.д.) на основе массива данных, полученных через вызов AJAX. Все хорошо работает для редактирования и добавления данных, но я не могу определить, как сделать отдельную копию массива (с отдельными копиями содержащихся объектов - по val, а не по ссылке), чтобы при удалении указанной строки данные, соответствующая строка удаляется из таблицы.

В настоящее время, поскольку содержащиеся объекты являются ref, даже когда я делаю копию массива, моя таблица удаляет последнюю строку (даже если индекс строки и данные правильно указаны и удалены в моем вызове AJAX).

handleRowDelete: function(rowIdx) {
     // Correct row 
     var row = this.state.data[rowIdx];

     // This makes a new array, but the contained objects are still by ref
     var rows = this.state.data.slice();

     // This contains the proper row that will be deleted. If this array is set to data, the table is updated to reflect just the one row - as expected.
     var throwout = rows.splice(rowIdx, 1);
     console.log(throwout);

     // Whether I set via the React.addons: 
     var newState = React.addons.update(this.state, {
         data: { $set: rows }
     });
     this.setState(newState);

     // Or just set the state again via this.setState(...)
     //this.setState({data: rows, add: false});

     // It always just removes the last row in the component render
     // Even though the proper row gets deleted following in AJAX call
     $.ajax({
     ...
},
...    

Я понимаю, что React не может сделать правильный diff, поэтому рендер не запускается, так что вы можете показать мне, как это должно быть обработано?

UPDATE. Соответствующий цикл:

var Grid = React.createClass({
    propTypes: {
        data: React.PropTypes.array.isRequired,
        onCellChange: React.PropTypes.func.isRequired,
        onRowCommit: React.PropTypes.func.isRequired
    },
    render: function() {
        var rows = this.props.data.map(function(rowData, index) {
            return <Row key={index} data={rowData} onCellChange={this.props.onCellChange.bind(null, index)} onRowCommit={this.props.onRowCommit.bind(null, index)} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
        }, this);

        return (
            <Table striped bordered hover responsive>
              <thead>
              <tr>
                <th className="col-sm-4">Order Subtotal (up to)</th>
                <th className="col-sm-2">Canada</th>
                <th className="col-sm-2">US</th>
                <th className="col-sm-2">International</th>
                <th className="col-sm-1"></th>
              </tr>
              </thead>
              <tbody>
                    {rows}
              </tbody>
            </Table>  
        );
    }
});
4b9b3361

Ответ 1

Вам нужно убедиться, что значение key остается константой для времени жизни экземпляра объекта. Как вы его кодировали, значение key основано на index на Array. Если вы удалите один элемент из Array, индексы будут обновлены, и так будут ключи. И, как результат, объект key изменился бы, и React, как представляется, неправильно применяет новые изменения массива (даже когда базовый массив изменился).

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

Ответ 2

Используйте уникальный ключ в Объектах данных, как показано ниже.

data = [
  {
    id: 0,
    contents: 'data 0',
  },
  {
    id: 3,
    contents: 'data 3',
  },
  {
    id: 4,
    contents: 'data 4',
  },
];


var rows = this.props.data.map(function(rowData, index) {
            return <Row key={rowData.id} data={rowData} onRowDelete={this.props.onRowDelete.bind(null, index)} />;
          }, this);

Реакция не перерисовывается, компонент имеет тот же ключ, что и раньше.