如何只修改react .map函数中的一个元素?

时间:2017-06-08 05:19:18

标签: javascript reactjs ecmascript-6

我有点新的反应,并且有点迷失在这里做什么。我从firebase加载数据并使用.map函数呈现该对象的道具以列出所有评论'在页面上,工作正常。我还想调用一个允许用户回复单个注释的组件(即地图中的一个特定元素),但正如此代码所期望的,当单击回复按钮时,它会在该元素的每个元素下显示被调用的组件。地图,这是不可取的。无论如何,在这种情况下,我可以只为地图的一个元素调用组件吗?

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>
  )
}

4 个答案:

答案 0 :(得分:1)

那是因为您对所有评论都使用单一状态。

<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}
);}

看看这是否有效。别忘了将新状态添加到构造函数中。

答案 1 :(得分:0)

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

&#13;
&#13;
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>
  )
}
&#13;
&#13;
&#13;

使用这种方法,您可以在用户点击回复评论按钮的不同评论中包含多个SetComment组件。

答案 2 :(得分:0)

您需要将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 :(得分:0)

我建议将其分为两部分。 CommentListComment组件。

<强>评论-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组件。

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