2015-03-10 6 views
13

Mam komponent, który generuje tabelę z wierszami danych (<tr> itp.) Na podstawie tablicy danych pobranych za pośrednictwem 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.React JS: jak prawidłowo usunąć element z this.state.data, gdzie dane są tablicą obiektów

Obecnie, ponieważ zawarte obiekty są przez ref, nawet gdy robię kopię tablicy, moja tabela ma ostatni wiersz usunięty (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 React nie może dokonać właściwego diff tak tynku nie jest wyzwalany, więc możesz mi pokazać, jak powinno to obchodzić?

AKTUALIZACJA. Istotne 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> 
     ); 
    } 
}); 
+0

Ponieważ nie masz wyświetlonego całego kodu, czy dodajesz specjalny atrybut 'klucz' do każdego' tr', aby React wiedział, co zostało poprawnie zmienione? http://facebook.github.io/react/docs/multiple-components.html#dynamic-children – WiredPrairie

+0

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

+0

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że, dla składników stanowych, które utrzymują dane w this.state przez przepustki renderowania, może to być bardzo problematycznym: W większości przypadków można ominąć ukrywanie elementów, zamiast je niszczyć " – Ted

Odpowiedz

14

Musisz upewnić się, że wartość key pozostaje na stałym poziomie przez cały okres istnienia instancji obiektu. Zgodnie z kodowaniem wartość key jest oparta na index na Array. Jeśli usuniesz jeden element z Array, indeksy zostaną zaktualizowane, podobnie jak klucze. W rezultacie zmieniono by obiekt key obiektu, a React będzie wyglądał, jakby nie stosował poprawnie zmian w nowej 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 utworzyć ją sztucznie (wystarczy przypisać unikalny numer do każdego obiektu).

1

Użyj unikalnego klucza w Data Objects 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); 

Reaguj nie ponownie renderuj składnik ma taki sam klucz jak wcześniej.