Pytanie React JS: jak poprawnie usunąć element z this.state.data, gdzie dane są tablicą obiektów


Mam komponent, który generuje tabelę z wierszami danych (<tr> itp.) w oparciu o tablicę danych pobranych przez wywołanie AJAX. Wszystko działa dobrze do edycji i dodawania danych, ale nie jestem w stanie określić, jak utworzyć wyraźną kopię tablicy (z oddzielnymi kopiami zawartych obiektów - przez val, a nie przez ref), aby po usunięciu określonego wiersza dane, odpowiedni wiersz jest usuwany ze stołu.

Obecnie, ponieważ zawarte obiekty są przez ref, nawet gdy robię kopię tablicy, moja tabela ma usunięty ostatni wiersz (mimo że indeks wiersza i dane są poprawnie przywoływane i usuwane w moim wywołaniu 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({
     ...
},
...    

Rozumiem, że React nie może dokonać poprawnego porównania, więc renderowanie nie zostanie uruchomione, więc czy możesz mi pokazać, jak to zrobić?

AKTUALIZACJA. Odpowiednia pętla:

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>  
        );
    }
});

13
2018-03-10 22:45


pochodzenie


Ponieważ nie pokazałeś całego kodu, dodajesz specjalny key przypisz do każdego tr żeby React wiedział, co właściwie się zmieniło? facebook.github.io/react/docs/... - WiredPrairie
Tak. Dodam do próbki. Jak już wspomniano, dodanie i edycja wiersza nie ma problemu (co nie byłoby możliwe, gdyby nie ustawiono klucza). - Ted
Być może powinienem po prostu ukryć usunięty wiersz zamiast go usuwać? Właśnie przeczytałem (co okazało się tuż nad tym, do czego się odwoływałem), że dla "Stateful Children" Dla większości komponentów, to nie jest wielka sprawa, jednak dla składników stanowych, które utrzymują dane w this.state w poprzek renderowania, może to być bardzo problematyczne, w większości przypadków można je ominąć ukrywając elementy zamiast je niszczyć " - Ted
Twój key nie jest unikalny dla wiersza. Używasz tylko indeksu ..., co oznacza, że ​​jeśli coś usuniesz, indeks się zmienił. - WiredPrairie
Klucz powinien być oparty na właściwości danych, która jest unikalna dla każdego wiersza, np. numer identyfikacyjny zamówienia. - Mark


Odpowiedzi:


Musisz upewnić się, że key wartość pozostaje stałą dla okresu istnienia instancji obiektu. Jak masz to zakodowane, key wartość jest oparta na index do Array. Jeśli usuniesz jeden element z Array, indeksy są aktualizowane, podobnie jak klucze. I w rezultacie obiekt key zmieni się, a React będzie wyglądał, jakby nie stosował poprawnie nowych zmian tablicy (nawet jeśli zmieniła się podstawowa tablica).

Będziesz musiał użyć unikalnej wartości z każdej instancji obiektu jako key lub utwórz sztucznie (po prostu przypisz unikalny numer do każdego obiektu).


14
2018-03-11 17:37





Użyj unikalnego klucza Obiekty danych jak poniżej.

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);

React nie renderuje ponownie komponentu ma ten sam klucz co wcześniej.


1
2018-03-24 11:45