2015-02-18 14 views
10

Ich versuche, einen Blog in React zu erstellen. In meiner Haupt-ReactBlog-Komponente mache ich einen AJAX-Aufruf an einen Knotenserver, um ein Array von Posts zurückzugeben. Ich möchte diese Postdaten an verschiedene Komponenten als Requisiten weitergeben.AJAX-Ergebnisse als Requisiten an untergeordnete Komponente übergeben

Insbesondere habe ich eine Komponente namens PostViewer, Post-Informationen anzuzeigen. Ich möchte, dass standardmäßig der Beitrag angezeigt wird, der über Requisiten von seinem übergeordneten Element übergeben wurde, und andernfalls Daten, die über einen Statusaufruf festgelegt werden.

Derzeit sieht der relevante Teil meines Codes wie folgt aus.

var ReactBlog = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [] 
    }; 
    }, 
    componentDidMount: function() { 
    $.get(this.props.url, function(data) { 
     if (this.isMounted()) { 
     this.setState({ 
      posts: data 
     }); 
     } 
    }.bind(this)); 
    }, 
    render: function() { 
    var latestPost = this.state.posts[0]; 
    return (
     <div className="layout"> 
     <div className="layout layout-sidebar"> 
      <PostList posts={this.state.posts}/> 
     </div> 
     <div className="layout layout-content"> 
      <PostViewer post={latestPost}/> 
     </div> 
     </div> 
    ) 
    } 
}); 

und das Kind Komponente:

var PostViewer = React.createClass({ 
    getInitialState: function() { 
    return { 
     post: this.props.post 
    } 
    }, 
    render: function() { 
    /* handle check for initial load which doesn't include prop data yet */ 
    if (this.state.post) { 
     return (
     <div> 
      {this.state.post.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 

Die oben genannten Arbeiten, wenn ich die in dem zu this.props macht mein Kind if-Anweisung und Inhalt tauschen * Allerdings würde dies bedeuten, dass ich ‚couldn. t den Inhalt später über den Zustand ändern, richtig?

TLDR: Ich möchte einen Standardbeitrag festlegen, um über Requisiten in einer Kindkomponente (Ergebnisse eines AJAX-Aufrufs) angezeigt zu werden, und ich möchte ändern, welcher Beitrag angezeigt wird, indem OnClick-Ereignisse (eines anderen) hinzugefügt werden Komponente), die den Status aktualisiert.

Ist das der richtige Weg?

Aktuelle Hierarchie meiner App-Komponenten sind:

React Blog 
- Post List 
    - Post Snippet (click will callback on React Blog and update Post Viewer) 
- Post Viewer (default post passed in via props) 

Dank!

EDIT:

Also, was ich am Ende tun war die Requisiten in ReactBlog Anbringen Wert auf Basis von this.state. Dadurch wurde sichergestellt, dass es aktualisiert wird, wenn ich den Status ändere und in untergeordneten Komponenten korrekt gerendert wurde. Dazu musste ich onClick-Callbacks über die verschiedenen untergeordneten Komponenten hinweg verketten. Ist das richtig? Es scheint, als könnte es SEHR chaotisch werden. Hier ist mein vollständiger Beispielcode:

var ReactBlog = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [], 
    }; 
    }, 
    componentDidMount: function() { 
    $.get(this.props.url, function(data) { 
     if (this.isMounted()) { 
     this.setState({ 
      posts: data, 
      post: data[0] 
     }); 
     } 
    }.bind(this)); 
    }, 
    focusPost: function(slug) { 
    $.get('/api/posts/' + slug, function(data) { 
     this.setState({ 
     post: data 
     }) 
    }.bind(this)); 
    }, 
    render: function() { 
    return (
     <div className="layout"> 
     <div className="layout layout-sidebar"> 
      <PostList handleTitleClick={this.focusPost} posts={this.state.posts}/> 
     </div> 
     <div className="layout layout-content"> 
      <PostViewer post={this.state.post}/> 
     </div> 
     </div> 
    ) 
    } 
}); 

var PostList = React.createClass({ 
    handleTitleClick: function(slug) { 
    this.props.handleTitleClick(slug); 
    }, 
    render: function() { 
    var posts = this.props.posts; 

    var postSnippets = posts.map(function(post, i) { 
     return <PostSnippet data={post} key={i} handleTitleClick={this.handleTitleClick}/>; 
    }, this); 

    return (
     <div className="posts-list"> 
     <ul> 
      {postSnippets} 
     </ul> 
     </div> 
    ) 
    } 
}); 

var PostSnippet = React.createClass({ 
    handleTitleClick: function(slug) { 
    this.props.handleTitleClick(slug); 
    }, 
    render: function() { 
    var post = this.props.data; 
    return (
     <li> 
     <h1 onClick={this.handleTitleClick.bind(this, post.slug)}>{post.title}</h1> 
     </li> 
    ) 
    } 
}); 

var PostViewer = React.createClass({ 
    getInitialState: function() { 
    return { 
     post: this.props.post 
    } 
    }, 
    render: function() { 
    /* handle check for initial load which doesn't include prop data yet */ 
    if (this.props.post) { 
     return (
     <div> 
      {this.props.post.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 

Noch ein Feedback/hoffte, das hilft zu bekommen gehofft!

+0

Sie tun alles richtig nach der Ausgabe. Die Verwendung eines Zustands in einer Elternkomponente, um den Kindern Requisiten zur Verfügung zu stellen, ist der richtige Weg. Ihr Problem bestand darin, dass "getInitialState" nur einmal für jede Komponente ausgeführt wird (es sei denn, es wird unmounted). Wenn Sie also den übergeordneten Status änderten, würde sich der Status des untergeordneten Status auch dann nicht ändern, wenn die untergeordneten Props geändert würden. – GonArrivi

Antwort

0

Ein Blog ist zum größten Teil statisch, so dass Sie die unveränderlichen Strukturen von React ausnutzen können, um die ganze Zeit "alles zu rendern", anstatt den Status zu verwenden.

Eine Option hierfür ist die Verwendung eines Routers (wie page.js) zum Abrufen von Daten.

Hier einige Code http://jsbin.com/qesimopugo/1/edit?html,js,output

Wenn Sie etwas nicht verstehen, nur um mich wissen lassen;), View-Datei

0

Staat, nicht für wiederverwendbare Komponenten Haupt reagieren sollte hier wie PostViewer, wird es nur render Beitrag Titel, wenn es Titel als Requisiten hat, sonst wird es leer.

var PostViewer = React.createClass({ 

    render: function() { 

    if (this.props.hasOwnProperty('title')) { 
     return (
     <div> 
      {this.props.title} 
     </div> 
    ) 
    } 
    return (
     <div/> 
    ) 
    } 
}); 
0

Sie sich von isMounted befreien und die Verwendung von context machen, wenn Sie Rückrufe vorbei sind mehrere Ebenen nach unten

2

Dies ist eine alte Frage, aber ich glaube immer noch relevant, also werde ich in werfen meine 2 Cent.

Idealerweise möchten Sie alle Ajax-Aufrufe in eine Aktionsdatei aufteilen, anstatt sie direkt in einer Komponente auszuführen. Ohne etwas wie Redux zu verwenden, um Ihnen zu helfen, Ihren Zustand zu verwalten (was ich zu diesem Zeitpunkt redux + react-redux empfehlen würde), könnten Sie etwas verwenden, das "Container-Komponenten" genannt wird Sie und dann Requisiten in der Komponente, die das Hauptlayout macht. Hier ist ein Beispiel:

// childComponent.js 
import React from 'react'; 
import axios from 'axios'; // ajax stuff similar to jquery but with promises 

const ChildComponent = React.createClass({ 
    render: function() { 
    <ul className="posts"> 
     {this.props.posts.map(function(post){ 
     return (
      <li> 
      <h3>{post.title}</h3> 
      <p>{post.content}</p> 
      </li> 
     ) 
     })} 
    </ul> 
    } 
}) 

const ChildComponentContainer = React.createClass({ 
    getInitialState: function() { 
    return { 
     posts: [] 
    } 
    }, 
    componentWillMount: function() { 
    axios.get(this.props.url, function(resp) { 
     this.setState({ 
     posts: resp.data 
     }); 
    }.bind(this)); 
    }, 
    render: function() { 
    return (
     <ChildComponent posts={this.state.posts} /> 
    ) 
    } 
}) 

export default ChildComponentContainer; 
+0

das ist definitiv ein guter Weg, es zu tun :) – Jon

Verwandte Themen