将AJAX结果作为道具传递给子组件

Jon*_*Jon 10 javascript ajax asynchronous reactjs

我正在尝试在React中创建一个博客.在我的主ReactBlog组件中,我正在对节点服务器进行AJAX调用以返回一组帖子.我想将此帖子数据作为道具传递给不同的组件.

特别是,我有一个名为PostViewer的组件,它将显示帖子信息.我希望它默认显示从其父级通过props传入的帖子,否则显示通过状态调用设置的数据.

目前,我的代码的相关部分看起来像这样.

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>
    )
  }
});
Run Code Online (Sandbox Code Playgroud)

和子组件:

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/>
    )
  }
});
Run Code Online (Sandbox Code Playgroud)

如果我将我孩子的渲染中的if语句和内容换成this.props,上面的工作就可以了.*但是,这意味着我以后无法通过状态更改内容,对吗?

TLDR:我想设置一个默认帖子,通过子组件中的props(AJAX调用的结果)进行查看,我希望能够通过添加onClick事件(另一个组件)来更改正在查看的帖子更新状态.

这是正确的方法吗?

我的应用程序组件的当前层次结构是:

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

谢谢!

编辑:

所以我最终做的是使用基于this.state的值在ReactBlog中附加道具.这确保了当我更改状态并在子组件中正确呈现时它会更新.但是,要做到这一点,我必须通过所有各种子组件链接onClick回调.它是否正确?看起来它可能变得非常混乱.这是我的完整示例代码:

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/>
    )
  }
});
Run Code Online (Sandbox Code Playgroud)

仍然希望得到一些反馈/希望这有帮助!

str*_*ser 0

博客在很大程度上是静态的,因此您可以利用 React 不可变结构来始终“渲染所有内容”,而不是使用状态。

一种选择是使用路由器(如page.js)来获取数据。

这是一些代码http://jsbin.com/qesimopugo/1/edit?html,js,output

如果您不明白,请告诉我;)