1

我有一个供稿,您可以在其中发布条目。然后,任何用户都可以喜欢这些条目。问题是,在您喜欢一个条目并继续编写自己的条目之后(从而将新条目推到提要的顶部),您单击的所有类似按钮的状态都将在视觉上撤消,以便查看显示的正确数据需要手动刷新。

这个问题非常奇特,不幸的是我没有发现任何可能与此相关的东西。

这是我的 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>
        );
    }
}

在父组件“log_entry.es6.jsx”中,我通过以下方式添加了类似的组件:

<Like entry={entry} key={entry.id} />

如果我可以提供更多信息,我会很乐意应要求提供。感谢您花时间审查我的问题!

4

2 回答 2

1

当您“继续编写自己的条目”时,是否会this.state在父组件中更新?如果是这样,我敢打赌它会导致Like重新渲染它的道具,这些道具已经过时了!

可以这样想:entry传入的<Like entry={entry} />数据仅包含在初始页面加载时为真的数据。当用户点击“赞”时,它会更新组件,但原来this.date的组件没有更新!Like entry

因此,如果某些原因导致Like从 重新渲染entry,它将使用陈旧的数据进行渲染!但是,如果您刷新页面,它将获取最新数据并正确呈现。

这听起来像是一个可能的原因吗?

我能想到的最好的解决方案是容器组件模式。在此模式中,只有一个组件(位于树的顶部)具有this.state. 它将数据作为道具发送给它的孩子。只有容器组件发送 AJAX 请求和更新this.state

在您的情况下,这意味着将postanddelete函数移动到父组件,并将它们Like作为事件处理程序传递(例如,<Like onLike={this.post} onUnlike={this.delete} ...>)然后,在 中Like,您可以将它们用作点击处理程序,例如,onClick={this.onLike}.

虽然这需要仔细组织,但它确实是有回报的,因为每一个render都是非常可预测的:唯一可以改变的是容器的this.state,其他一切this.props都只渲染!

于 2016-02-15T02:17:35.550 回答
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>
        );
    }
}

我添加的是发布和删除功能上的 2 行。

this.props.entry.liked = true;
this.props.entry.likes_count = likes;

this.props.entry.liked = false;
this.props.entry.likes_count = likes;

只需更新此条目的道具。我不确定这是否是最好的解决方案,但对我来说,它可以帮助我将功能保留在它所属的位置,当然它也可以工作。

于 2016-02-15T12:36:10.810 回答