我所拥有的是一个可以发布条目的Feed。然后,任何用户都可以喜欢这些条目。问题是,在您喜欢一个条目并继续编写自己的条目之后(因此将新条目推送到Feed的顶部),您单击的所有类似按钮的状态将在视觉上撤消,以便看到显示的正确数据需要手动刷新。
这个问题非常奇怪,遗憾的是我找不到任何可能与此相关的内容。
这是我的Like组件的代码(like.es6.jsx):
class Like extends React.Component {
constructor(props){
super(props);
this.state={
like: this.props.entry.liked,
likes: this.props.entry.likes_count
}
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
post () {
if(!(this.state.like)){
$.ajax({
method: "POST",
url: "/api/v1/likes",
data: {
log_entry_id: this.props.entry.id
},
})
.then( (response) => {
this.setState({like: true})
let likes = this.state.likes;
likes++;
this.setState({likes: likes})
});
}
}
delete(){
if(this.state.like){
$.ajax({
method: "DELETE",
url: "/api/v1/likes/" + this.props.entry.id
})
.then( (response) => {
this.setState({like: false})
let likes = this.state.likes;
likes--;
this.setState({likes: likes})
});
}
}
render () {
let show_likes = "";
if(this.state.like) {
show_likes = (this.state.likes > 1) ? ("You and " + (this.state.likes - 1) + ((this.state.likes == 2) ? (" other person") : (" others" )) + (" like this.")) : ("You like this.");
}else if(this.state.likes > 0){
show_likes = (this.state.likes == 1) ? (this.state.likes + " person likes this.") : (this.state.likes + " people like this.");
}
let like_button = this.state.like ?
<a onClick={this.delete} className=" pull-right"><i className="fa fa-thumbs-o-down"></i> Dislike</a> :
<a onClick={this.post} className=" pull-right"><i className="fa fa-thumbs-o-up"></i> Like</a>
return (
<div>
<span>
{show_likes}
</span>
{like_button}
</div>
);
}
}
在父组件&#39; log_entry.es6.jsx&#39;我已通过以下方式添加了我喜欢的组件:
<Like entry={entry} key={entry.id} />
如果我能提供更多信息,我会很乐意应要求提供。感谢您抽出时间审核我的问题!
答案 0 :(得分:1)
当您“继续编写自己的条目”时,是否会在父组件中更新this.state
?如果是这样,我敢打赌它会导致Like
重新渲染其道具,这些道具已经过时了!
以这种方式思考:传递到entry
的{{1}}仅包含在初始页面加载时为真的数据。当用户点击“赞”时,它会更新<Like entry={entry} />
组件的this.date
,但原始 Like
未更新!
因此,如果某些内容导致entry
从Like
重新渲染,则会使用陈旧数据进行渲染!但是,如果刷新页面,它将获取最新数据并正确呈现。
这听起来像是一个可能的原因吗?
我能想到的最佳解决方案是container component模式。在此模式中,只有一个组件(位于树的顶部)具有entry
。它将数据作为道具发送给子项。只有容器组件发送AJAX请求并更新this.state
。
在您的情况下,这意味着将this.state
和post
函数移动到父组件,并将它们作为事件处理程序传递给delete
(例如,Like
然后,在<Like onLike={this.post} onUnlike={this.delete} ...>
中,您可以将它们用作点击式处理程序,例如Like
。
虽然这需要精心组织,但它确实是值得的,因为每个onClick={this.onLike}
都是可预测的:唯一可以改变的是容器的render
,其他所有内容只能从this.state
呈现!
答案 1 :(得分:0)
我尝试将函数和状态处理程序移动到父组件。然而事实证明这很麻烦,因为我的Like按钮的父母也有一个父母(也许我可以进一步用尽这种方法,但我发现了一种不同的方式)。
我的解决方案最终成为了这个:
class Like extends React.Component {
constructor(props){
super(props);
this.state={
like: this.props.entry.liked,
likes: this.props.entry.likes_count
}
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
post () {
if(!(this.state.like)){
$.ajax({
method: "POST",
url: "/api/v1/likes",
data: {
log_entry_id: this.props.entry.id
},
})
.then( (response) => {
this.setState({like: true})
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
this.props.entry.liked = true;
this.props.entry.likes_count = likes;
});
}
}
delete(){
if(this.state.like){
$.ajax({
method: "DELETE",
url: "/api/v1/likes/" + this.props.entry.id
})
.then( (response) => {
this.setState({like: false})
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
this.props.entry.liked = false;
this.props.entry.likes_count = likes;
});
}
}
render () {
let show_likes = "";
if(this.state.like) {
show_likes = (this.state.likes > 1) ? ("You and " + (this.state.likes - 1) + ((this.state.likes == 2) ? (" other person") : (" others" )) + (" like this.")) : ("You like this.");
}else if(this.state.likes > 0){
show_likes = (this.state.likes == 1) ? (this.state.likes + " person likes this.") : (this.state.likes + " people like this.");
}
let like_button = this.state.like ?
<a onClick={this.delete} className=" pull-right"><i className="fa fa-thumbs-o-down"></i> Dislike</a> :
<a onClick={this.post} className=" pull-right"><i className="fa fa-thumbs-o-up"></i> Like</a>
return (
<div>
<span>
{show_likes}
</span>
{like_button}
</div>
);
}
}
我在post和delete函数中添加的是2行。
this.props.entry.liked = true;
this.props.entry.likes_count = likes;
this.props.entry.liked = false;
this.props.entry.likes_count = likes;
只需更新此条目的道具即可。我不确定这是否是最好的解决方案,但对我而言,这有助于我保留其所属的功能,当然它也可以。