【问题标题】:How to update upvote counter for individual elements instead of all of them at once with React如何使用 React 一次更新单个元素而不是所有元素的投票计数器
【发布时间】:2019-11-22 02:04:02
【问题描述】:

新手开发者学习 React。

我正在尝试在 React 中为博客文章创建一个投票功能,但是当我点击投票按钮时,我会同时投票所有的博客帖子卡片而不是单个卡片。

我该如何解决这个问题?我相信问题可能出在我设置 setState 的方式上?但我可能错了,正在寻求帮助。

提前致谢!

====

class Posts extends Component {

    state= {
        points: 0
    }


    componentDidMount() {
        this.props.fetchPosts()
    }

    UNSAFE_componentWillReceiveProps(nextProps) {
        if (nextProps.newPost) {
          this.props.posts.unshift(nextProps.newPost);
        }
      }


    handleClick = () => {
        this.setState({points: this.state.points + 1})
    }

    render() {

        const postItems = this.props.posts.map((post, index) => (

            <div key={index} className="ui three stackable cards">
                <div className="ui card">
                    <div className="content">
                        <div className="header">{post.title}</div>
                        <div className="meta"> {post.author}</div>
                        <div className="description">
                        <p>{post.body}</p>
                        </div>
                    </div>
                    <div className="extra content">
                        <i className="check icon"></i>
                        {this.state.points} Votes
                    </div>
                    <button className="ui button" 
                        type="submit" 
                        onClick={this.handleClick}>Add Point</button>
                </div>
            </div>

        ))

        return (
            <div>
                <br />
                <h2 className="ui header">
                    <i className="pencil alternate icon"></i>
                <div className="content">
                    Blog Feed
                    <div className="sub header"><a href="/posts/new">Create New Post!</a></div>
                </div>
                </h2>
                {postItems}
            </div>
        )
    }
}

【问题讨论】:

  • 您的帖子有唯一标识符吗?

标签: javascript reactjs react-redux state


【解决方案1】:

您有一个组件存储所有帖子的“点”状态。为了实现您描述的功能,每个帖子都应该是具有自己状态的自己的组件。

class Post extends Component {

    state = {
        points: 0
    }

    handleClick = () => {
        this.setState({points: this.state.points + 1})
    }

    render = () =>
        <div key={index} className="ui three stackable cards">
                <div className="ui card">
                    <div className="content">
                        <div className="header">{this.props.title}</div>
                        <div className="meta"> {this.props.author}</div>
                        <div className="description">
                        <p>{this.props.body}</p>
                        </div>
                    </div>
                    <div className="extra content">
                        <i className="check icon"></i>
                        {this.state.points} Votes
                    </div>
                    <button className="ui button" 
                        type="submit" 
                        onClick={this.handleClick}>Add Point</button>
                </div>
            </div>
    }
}

【讨论】:

    【解决方案2】:

    因为你只有一个指示物,所以你对每一张牌都投了赞成票。应该为每张卡片定义一个单独的计数器。

    state = {}; // dictionary-a-like state structure
    
    handleClick = (id) => () => {
        this.setState((prevState) => ({ 
           [id]: prevState[id] ? prevState[id] + 1 : 1, // check and increment counter
        }));
    }
    
    onClick={this.handleClick(post.id)} // call function with post.id as argument
    
    {this.state[post.id] || 0} Votes // display votes for every card
    

    注意:我假设每张卡都有自己的唯一 ID,如果没有 - index 也可以派上用场。

    【讨论】:

    • 非常酷,我从你的代码和你上面的尼克那里学到了东西。 QQ tho,为什么它更好,或者将 state 设置为空对象而不是整数 0 有什么好处?
    • @RafaelLopez Integer 0 没有意义,因为它对于每张卡都是静态的。您需要一个灵活的解决方案,以便每张单独的卡片都有自己的计数器 :) 对象非常适合这些情况,就像您的一样。
    【解决方案3】:

    每个帖子都需要一个计数器。目前,所有帖子只有一个计数器,这意味着它们都显示相同的值。

    实现这一点的最佳方法可能是将您的帖子分成自己的组件,并让其跟踪计数器。

    【讨论】:

      【解决方案4】:

      以下解决方案使用帖子 ID(如果有)在有状态的 points 对象中创建密钥。然后,在单击时,您可以添加到正确的点键。

      state = {
        points: {}
      }
      
      handleClick = postId => {
        this.setState({ 
          points: {
            ...this.state.points,
            [postId]: (this.state.points[postId] || 0) + 1
          }
        })
      }
      
      const postItems = this.props.posts.map((post, index) => (
        ...
        <div className="extra content">
          <i className="check icon"></i>
          {this.state.points[post.id] || 0} Votes
        </div>
        <button 
          className="ui button" 
          type="submit" 
          onClick={() => this.handleClick(post.id)}
        >
          Add Point
        </button>
        ...
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-21
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        相关资源
        最近更新 更多