Я пытаюсь создать блог в React. В моем основном компоненте ReactBlog я выполняю вызов AJAX на сервере node, чтобы вернуть массив сообщений. Я хочу передать эти данные сообщения различным компонентам в качестве реквизита.
В частности, у меня есть компонент, называемый PostViewer, который будет отображать информацию о сообщении. Я хочу, чтобы он по умолчанию показывал сообщение, отправленное из его родителя через реквизиты, и в противном случае показывал данные, которые устанавливаются с помощью государственного вызова.
В настоящее время соответствующие части моего кода выглядят следующим образом.
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. * Однако это означало бы, что я не смог бы изменить содержимое позже через состояние, правильно?
TL;DR: я хочу установить пост по умолчанию для просмотра через реквизиты в дочернем компоненте (результаты вызова 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)
Спасибо!
EDIT:
Итак, что я закончил делать, это привязать реквизит в ReactBlog, используя значение, основанное на this.state. Это гарантировало, что он обновляется, когда я меняю состояние и правильно рисую дочерние компоненты. Однако для этого мне пришлось подключать callback-запросы 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/>
)
}
});
Все еще надеемся получить некоторые отзывы/надеюсь, что это поможет!