2016-08-07 11 views
2

Ich versuche, Daten in einer Komponente einer React-Anwendung erhalten übergeben. Bei Erfolg nehme ich die empfangenen Daten und setze den Zustand und versuche dann, diese Daten als eine Eigenschaft der nächsten Komponente zu übergeben. Sobald ich innerhalb der zweiten Komponente bin, muss ich auf die übergebenen Daten über this.state zugreifen, damit ich später den Status in dieser Komponente ändern kann. Es scheint, dass ein Problem mit dem DOM-Rendering auftritt, bevor die Daten vom Dienst empfangen werden. Ich habe versucht, ein bereits geladenes Array von Werten anstelle von this.state.data in <List data={this.state.data}/> zu übergeben und es scheint gut zu funktionieren. Wie kann ich sicherstellen, dass ich die Daten vom Dienst erhalten habe, bevor ich das DOM rendere, so dass die Daten vollständig an die einzelnen Komponenten weitergegeben werden.Übergeben von Ajax/Dienstdaten zwischen Komponenten in React.js

EDIT: vollständige Umsetzung des Listenelement hinzugefügt, so die Verwendung von this.state Diese

erklären, ist im Grunde, was ich zu tun versucht:

var Box = React.createClass({ 

    getInitialState: function() { 
    return {data: []}; 
    }, 

    loadTodosFromServer: function() { 
    $.ajax({ 
     url: this.props.url, 
     dataType: 'json', 
     type: 'GET', 
     cache: false, 
     success: function(dataResponse) { 
     this.setState({data: dataResponse}); 
     }.bind(this), 
     error: function(xhr, status, err) { 
     console.error(this.props.url, status, err.toString()); 
     }.bind(this) 
    }); 
    }, 

    componentDidMount: function() { 
    this.loadFromServer(); 
    }, 

    render: function() { 
    return (<List data={this.state.data}/>); 
    } 
}); 


var List = React.createClass({ 

    getInitialState: function() { 
    return {data: this.props.data}; 
    }, 

dragStart: function(e) { 
    this.dragged = e.currentTarget; 
    e.dataTransfer.effectAllowed = 'move'; 
    // Firefox requires dataTransfer data to be set 
    e.dataTransfer.setData("text/html", e.currentTarget); 
}, 

dragEnd: function(e) { 
    this.dragged.style.display = "block"; 
    this.dragged.parentNode.removeChild(placeholder); 
    // Update data 
    var data = this.state.data; 
    var from = Number(this.dragged.dataset.id); 
    var to = Number(this.over.dataset.id); 
    if(from < to) to--; 
    if(this.nodePlacement == "after") to++; 
    data.splice(to, 0, data.splice(from, 1)[0]); 
    this.setState({data: data}); 
}, 

dragOver: function(e) { 
    e.preventDefault(); 
    this.dragged.style.display = "none"; 
    if(e.target.className == "placeholder") return; 
    this.over = e.target; 
    // Inside the dragOver method 
    var relY = e.clientY - this.over.offsetTop; 
    var height = this.over.offsetHeight/2; 
    var parent = e.target.parentNode; 

    if(relY > height) { 
    this.nodePlacement = "after"; 
    parent.insertBefore(placeholder, e.target.nextElementSibling); 
    } 
    else if(relY < height) { 
    this.nodePlacement = "before" 
    parent.insertBefore(placeholder, e.target); 
    } 
}, 

    render: function() { 
    var results = this.state.data; 
     return (
     <ul> 
      { 
       results.map(function(result, i) { 
       return (
        <li key={i}>{result}</li> 
       ) 
       }) 
      } 
     </ul> 
    ); 
    } 
    }); 


ReactDOM.render(
    <Box url="/api/comments"/>, document.getElementById('content') 
); 
+0

Haben Sie den Zustand in der List-Komponente ändern? – KumarM

+0

@kumarm Ja, das war meine Absicht, als ich mich dafür entschied, this.state.data – NightMarcher

Antwort

2

Der Grund, warum Ihre Datenlast Nach dem Laden der Komponente wird das Rendern der Daten aufgrund dieser Zeile in Ihrer List.render-Funktion nicht ausgeführt:

Essenti Sie haben jedoch eine Kopie Ihrer ursprünglichen Requisiten erstellt und sie mithilfe der Methode "getInitialState" dem Status in der List-Komponente zugewiesen. Und danach werden dein Zustand und deine Requisiten gelöst. Das heißt, wenn sich die Datei "props.data" in der List-Komponente ändert, weiß der Status nichts darüber, und daher wird nichts neu gerendert.

Verwenden Sie also anstelle von state zum Initialisieren der Ergebnisvariablen requisiten.

var results = this.props.data 

Hier ist, wie es aussehen würde:

var List = React.createClass({ 

    render: function() { 
    var results = this.props.data; 
     return (
     <ul> 
      { 
       results.map(function(result, i) { 
       return (
        <li key={i}>{result}</li> 
       ) 
       }) 
      } 
     </ul> 
    ); 
    } 
    }); 

nun Änderungen jederzeit die Daten, Requisiten aktualisiert werden und schließlich die Ergebnisse neu gerendert bekommen.

die Kommentare vom OP zur Adresse aktualisiert:

Wenn Sie den Zustand der Liste aktualisieren mögen, wollen aber jedes Mal, wenn die Requisiten bei der Mutter Änderung informiert werden, dann sollten Sie die Methode verwenden, componentWillReceiveProps, so dass beim Empfang der Daten die untergeordnete Liste benachrichtigt wird. Und in dieser Methode können Sie den neuen Status festlegen:

componentWillReceiveProps: function(newProps) { 
    this.setState({data: this.props.data}); 
} 

Sobald Sie dies tun, wird Reagieren Rendern der Liste für Sie.

Ein weiteres Update: Um zu zeigen, wie das funktioniert, ich habe here zusammen ein Beispiel setzen.

Und hier ist der JS-Code dafür:

let todos = ["Run","Swim","Skate"]; 

class MyList extends React.Component{ 
    componentWillMount() { 
    console.log("Props are: ", this.props); 
    this.setState({list: this.props.items}); 
    } 

    componentWillReceiveProps(newProps) { 
    console.log("Received Props are: ", newProps); 
    this.setState({list: newProps.items}); 
    } 

    render() { 
    return (<ul> 
      {this.state.list.map((todo) => <li>{todo}</li>)} 
      </ul>); 
    } 
} 

class App extends React.Component{ 
    constructor() { 
     super(); 
     console.log("State is: ", this.state); 
    } 

    componentWillMount() { 
    this.setState({items: ["Fly"]}); 
    } 

    componentDidMount() { 
    setTimeout(function(){ 
     console.log("After 2 secs"); 
     this.setState({items: todos}); 
    }.bind(this), 2000); 
    } 

    render() { 
     return (<MyList items={this.state.items}/>); 
    } 
} 


ReactDOM.render(<App/>, document.getElementById("app")); 
+0

zu verwenden. Ich änderte diesen Wert von Requisiten in Zustand, so dass ich den Zustand aktualisieren konnte, nachdem die erste Liste geladen wurde. Meine Absicht ist es, eine Liste von Elementen zu erstellen und sie dann neu anordnen zu können, nachdem die ursprüngliche Liste durch eine Drag & Drop-Schnittstelle generiert wurde. Kann ich die this.props-Methode weiterhin verwenden, um diese Art von Funktionalität zu implementieren?Ich habe diesen Teil zum leichteren Lesen weggelassen. – NightMarcher

+0

Danke @NightMarcher. Ich habe meine Antwort entsprechend aktualisiert. – KumarM

+0

@NightMarcher Hat dies Ihr Problem gelöst? Wenn ja, kannst du das bitte als Antwort markieren. Vielen Dank. – KumarM

Verwandte Themen