【发布时间】:2015-04-20 03:38:57
【问题描述】:
我正在尝试在 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>
)
}
});
和子组件:
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/>
)
}
});
如果我将我孩子的渲染中的 if 语句和内容换成 this.props,则上述方法有效。* 但是,这意味着我以后无法通过状态更改内容,对吗?
TLDR:我想设置一个默认帖子以通过子组件中的道具查看(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)
谢谢!
编辑:
所以我最终做的是使用基于 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/>
)
}
});
仍然希望得到一些反馈/希望这会有所帮助!
【问题讨论】:
-
你在编辑后就可以了。使用父组件中的状态为子组件提供道具是要走的路。你的问题是“getInitialState”只对每个组件执行一次(除非它被卸载)所以当你改变父状态时,即使子道具也会改变,它的状态不会。
标签: javascript ajax asynchronous reactjs