2017-02-22 2 views
1

bin ich ein bisschen grün, wenn es um ReactJS kommt, aber es ist Teil eines Projekts, ich arbeite und ich versuche zu verstehen, wie man richtig eine Komponente Zustand mutieren:Rendering Zeilen dynamisch aus this.state

ich habe eine Tabellenkomponente, die in ES6 als solche deklariert ist:

class EmailStatisticTable extends React.Component { 
    constructor (props) { 
     super(props); 
     this.state = { 
      event_id: props.event_id, 
      statistics: [], 
      rows: [] 
     } 
    } 

    componentDidMount() { 
     var self = this; 
     $.getJSON('/events/' + this.state.event_id + '/emails/stats', function(resp){ 
      self.state.statistics = resp; 
      self.state.statistics.forEach(function(statistic) { 
       self.state.rows.push(<EmailStatisticRow statistic={statistic}/>); 
      }); 
     }); 
     console.log(self.state.rows); 
    } 

    render() { 
     return (
      <table className="table table-striped table-hover"> 
       <thead> 
        <tr> 
         <th> Recipient Type </th> 
         <th></th> 
        </tr> 
       </thead> 
       <tbody>{this.state.rows}</tbody> 
      </table> 
     ) 
    } 
} 

Die Idee dabei ist, dass die Zeilen dynamisch gemacht werden würde, wenn this.state.rows Änderungen. Ich kann sehen, dass self.state.rows innerhalb der componentDidMount Methode ein Array von EmailStatisticRow Komponenten korrekt erstellt. Welches ist unten erklärt:

class EmailStatisticRow extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = { 
      statistic : props.statistic 
     } 
    } 
    render() { 
     return (
      <tr> 
       <td>{this.state.statistic.record_type}</td> 
       <td>{this.state.statistic.count}</td> 
      </tr> 
     ) 
    } 
} 

Allerdings sind die Reihen nie auf das DOM hinzugefügt, nachdem die Daten vom Server über $.getJSON() zurückgesendet wird.

Ich denke, mein Problem kann ein grundlegendes Missverständnis der state Management und es ist Mutabilität/Unveränderlichkeit in ReactJS.

Kann jemand Klarheit zu diesem Thema geben?

Danke.

Antwort

2

Sie sollten den Status über die Methode setState() statt direkt setzen.

So ersetzen:

self.state.statistics = resp; 
      self.state.statistics.forEach(function(statistic) { 
       self.state.rows.push(<EmailStatisticRow statistic={statistic}/>); 
      }); 

Mit

this.setState({ 
    statistics: resp 
}) 

Und dann anstatt die Zeilen zuweisen, in der Funktion

<tbody>{this.state.rows}</tbody> 

mit

<tbody>{this.state.statistics.map(function(row) { 
    return <EmailStatisticRow statistic={row}/> 
})}</tbody> 
ersetzen machen

Edit: für eine kleine weitere Erklärung - der SetState wird eine render auslösen und alle Statistikzeilen werden EmailStatisticRow-Komponenten zugeordnet werden.

+1

Fantastisch.Dies ist die genaue Information, die ich brauchte, um voranzukommen. Ich kann sehen, wo meine Fehler jetzt waren. Ich schätze es sehr. – Ohgodwhy

+0

Ich bin froh, dass ich helfen konnte – paqash

1

In Reaktion you should not mutate state direkt wie folgt aus:

self.state.rows.push(<EmailStatisticRow statistic={statistic}/>); 

Verwenden Sie stattdessen setState():

self.setState({rows: newRows}); 

Es ist auch not advised to store rendered elements in state (<EmailStatisticRow>), speichern nur die statistics Daten in Staat:

self.setState({statistics: resp}); 

Und machen die Liste in Ihrer render Funktion, zum Beispiel mit map():

render() { 
    return (
     <table className="table table-striped table-hover"> 
      <thead> 
       <tr> 
        <th> Recipient Type </th> 
        <th></th> 
       </tr> 
      </thead> 
      <tbody> 
       { this.state.statistics.map(statistic => <EmailStatisticRow statistic={statistic}/>) } 
      </tbody> 
     </table> 
    ) 
} 

Mit setState() Ursachen render() genannt werden, und machen Sie sollten immer ein volles Ergebnis auf den Requisiten und Staat basiert geben. Dies ist das grundlegende Rendering-Muster von React, das es vorhersagbar macht.

Verwandte Themen