【问题标题】:How to modify only one element in a react .map function?如何只修改 react .map 函数中的一个元素?
【发布时间】:2017-11-09 15:59:03
【问题描述】:

我对反应有点陌生,对在这里做什么有点迷茫。我正在从 firebase 加载数据并使用 .map 函数渲染该对象的道具,以列出页面上的所有“cmets”,效果很好。我还想调用一个组件,允许用户回复单个评论(即地图中的一个特定元素),但正如这段代码所预期的那样,当点击回复按钮时,它会在每个元素下显示被调用的组件地图,这是不可取的。在这种情况下,无论如何我可以只为地图的一个元素调用组件吗?

changeIsReply() {
  this.setState(
    {isReply: !this.state.isReply,}
  );
}    

  render() {

  return (
    <div>
    <ul className="list-group">
    {Object.values(this.props.commentInfo).map((data) =>
      data.map((secondData, i) =>
        <div className="commentHolder" key={i}>
            <p>{secondData.text}</p>
            <p>{secondData.category}</p>
            <p>{secondData.organization}</p>
            <button> UpButton </button> <br />
            <button> DownButton </button>
            <button onClick = {this.changeIsReply} > Reply </button>
            {this.state.isReply ? <SetComment id={secondData.key} /> : null}
        </div>
      )
    )}
    </ul>
    </div>
  )
}

【问题讨论】:

    标签: javascript reactjs ecmascript-6


    【解决方案1】:

    那是因为您对所有 cmets 使用单一状态。

    <button onClick = {() => this.changeIsReply(secondData.key)} > Reply </button>
    
    {this.state.isReply && this.state.clickedComment == {secondData.key} ? <SetComment id={secondData.key} /> : null}
    

    并将您的 changeIsReply() 更改为:

    changeIsReply(clickedId) {
        this.setState({
            isReply: !this.state.isReply, 
            clickedComment: clickedId
        });
    }
    

    看看这是否有效。不要忘记将新状态添加到您的构造函数中。

    【讨论】:

      【解决方案2】:

      您需要将 isReply 保留为数组数组,并根据单击的评论的索引,仅更新正确的值,例如

      state= {
         isReply: [[]]
      }
      changeIsReply(i, j) {
        var isReply = [...this.state.isReply]
        if(isReply[i] === undefined) {
          isReply.push([true]) = 
        } else {
          if(isReply[i][j] === undefined) {
            isReply[i].push(true)
          } else {
             isReply[i][j] = !isReply[i][j]
          }
        }
        this.setState(
          {isReply}
        );
      }    
      
        render() {
      
        return (
          <div>
          <ul className="list-group">
          {Object.values(this.props.commentInfo).map((data, i) =>
            data.map((secondData, j) =>
              <div className="commentHolder" key={j}>
                  <p>{secondData.text}</p>
                  <p>{secondData.category}</p>
                  <p>{secondData.organization}</p>
                  <button> UpButton </button> <br />
                  <button> DownButton </button>
                  <button onClick = {() => this.changeIsReply(i, j)} > Reply </button>
                  {this.state.isReply[i][j] ? <SetComment id={secondData.key} /> : null}
              </div>
            )
          )}
          </ul>
          </div>
        )
      }
      

      【讨论】:

        【解决方案3】:

        您可以跟踪哪个评论应该有 SetComment 组件。

        constructor(props) {
          super(props);
          this.state = {
            // init commentReplyIds as empty array
            commentReplyIds : [],
            // ... rest of your state
          }
        }
        
        changeIsReply(commentId) {
          const newCommentReplyIds = [...this.state.commentReplyIds. commentId];
          this.setState(
            {commentReplyIds: newCommentReplyIds}
          );
        }    
        
          render() {
          // in here I am using the data.text as the unique id of each comment, you can use other serializable value.
          return (
            <div>
            <ul className="list-group">
            {Object.values(this.props.commentInfo).map((data) =>
              data.map((secondData, i) =>
                <div className="commentHolder" key={i}>
                    <p>{secondData.text}</p>
                    <p>{secondData.category}</p>
                    <p>{secondData.organization}</p>
                    <button> UpButton </button> <br />
                    <button> DownButton </button>
                    <button onClick = {() => this.changeIsReply(secondData.text)} > Reply </button>
                    {this.state.commentReplyIds.includes(secondData.text) ? <SetComment id={secondData.key} /> : null}
                </div>
              )
            )}
            </ul>
            </div>
          )
        }

        通过这种方法,您可以拥有多个SetComment 组件,位于用户单击了回复评论按钮的不同cmet 中。

        【讨论】:

          【解决方案4】:

          我建议把它分成两个部分。 CommentListComment 组件。

          comment-list.js

          import Comment from './comment';
          
          class CommentList extends Component{
              render(){
              return(
                  <div>
                  <ul className="list-group">
                          {Object.values(this.props.commentInfo).map((data) =>
                          data.map((secondData, i) =>
                              <Comment text={secondData.text} category={secondData.category} organization={secondData.organization} key={secondData.key} />
                )
                  </ul>
                </div>
              )
            }
          }
          

          comment.js

          class Comment extends Component {
              constructor(props){
              super(props);
              this.state = {
                  isReply: false
              }
            }
            changeIsReply = () => {
              this.setState(
                {isReply: !this.state.isReply,}
              );
            }   
              render(){
              const {text, category, organization, key} = this.props;
              return(
                <div className="commentHolder" key={i}>
                  <p>{text}</p>
                  <p>{category}</p>
                  <p>{organization}</p>
                  <button> UpButton </button> <br />
                  <button> DownButton </button>
                  <button onClick = {this.changeIsReply} > Reply </button>
                  {this.state.isReply ? <SetComment id={key} /> : null}
                </div>
              )
            }
          }
          
          export default Comment;
          

          这样,每个评论都可以控制自己的状态以及是否显示SetComment 组件。

          尝试制作更多组件,而不是将所有标记放在单个渲染方法中。这也有助于组织您的代码,以便您将每组值映射到一个组件,我觉得这让您更容易理解。

          【讨论】:

            猜你喜欢
            • 2020-10-10
            • 1970-01-01
            • 2020-12-10
            • 2018-09-02
            • 2020-04-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多