为.map()函数中的每个Component绑定onClick

时间:2016-11-25 07:26:42

标签: reactjs

我创建了一个父组件PicturesFetch,它呈现另一个(子)组件Picture,它会在里面呈现带有图片的div。现在,为了渲染PicturePicturesFetch遍历一个对象(图片),并使用.map()函数创建多个带有图像的div。我希望能够更改单独创建的每个元素的状态。这是我到目前为止所尝试的,测试的绑定是一个接一个地尝试,而不是一起尝试:

PictureFetch.js

class PicturesFetch extends React.Component {
constructor(props) {
    super(props);
        this.state = { 
            isSelected: true,
            pictureClassName: "picture-div green",
            pics : [/*Object witch contains names and src of the images*/]
        };
    this.handlePictureClick = this.handlePictureClick.bind(this); /*#1 tested bind*/
}
handlePictureClick (isSelected){
    if (!isSelected) {
        this.setState({
            isSelected: true,
            pictureClassName: "picture-div green"
        })
    } else {
        this.setState({
            isSelected: false,
            pictureClassName: "picture-div none"
        })
    }
}
render() {
    var changeClass = this.state.pictureClassName;
    var handlePictureClick = this.handlePictureClick.bind(this); /*#2 tested bind*/
    var pics = this.state.pics.map(function(pic, i){
        if (/*something*/) {
            return (
            <div className="pic-div" key={i} >
                <Picture 
                    isSelected={isSelected}
                    pictureClassName={changeClass}
                    onClick={handlePictureClick.bind(this, isSelected)} /*#3 tested bind*/
                />
            </div>
            });
        } 
    return (
    <div className="Options-container">
        <div className="container">{pics}</div>
    </div>
    );
}}

Picture.js

class Picture extends React.Component  {
constructor(props) {
    super(props);
        this.state = { 
            isSelected: true,
            pictureClassName: "picture-div green" 
        };
}
render() {
    var pictureClassName = this.props.pictureClassName;
    return (
        <div onClick={this.props.onClick} className={pictureClassName}>
            <img src={this.props.src} alt={this.props.name} />
            <h5>{this.props.name}</h5>
        </div>
    )
}}

我简化了我的代码示例。现在,通过将绑定放置在#1和#2位置,将所有图像状态一起更改,而在#3中给出错误无法读取属性'setState'未定义

哪个是绑定onClick函数的正确位置,所以我可以分别访问每个图像状态?也许我的结构存在缺陷?提前谢谢。

3 个答案:

答案 0 :(得分:4)

您可以使用#1或#3绑定onClick函数。在#3中,你在handlePictureClick中缺少这个。

并且第二部分分别访问每个图像状态。您必须将isSelected和pictureClassName键放在每个pic对象中。 和handlePictureClick可以修改如下。

     handlePictureClick (pic){
          this.setState(pics : this.state.pics.map(function(picture){
              if(picture.id === pic.id){
                if(picture.isSelected){
                   picture.isSelected = false;
                   picture.pictureClassName = "picture-div none";
                } else {
                   picture.isSelected = true;
                   picture.pictureClassName = "picture-div green";
                }

              }
              return picture; 
          ));
    }

  render() {
     var changeClass = this.state.pictureClassName;
        var pics = this.state.pics.map(function(pic, i) {
            if (/*something*/) {
                return (
                <div className="pic-div" key={i} >
                    <Picture 
                        isSelected={pic.isSelected}
                        pictureClassName={changeClass}
                        onClick={this.handlePictureClick.bind(this, pic)} 
                    />
                </div>
                }
            });
        return (
        <div className="Options-container">
            <div className="container">{pics}</div>
        </div>
        );
}

答案 1 :(得分:3)

添加@dulwalanise给出的解决方案可以通过将map函数绑定到上下文来解决问题。 this.handlePictureClick未定义,因为此处this未引用组件的上下文而非地图中的函数

使用此

handlePictureClick (pic){
      this.setState(pics : this.state.pics.map(function(picture){
          if(picture.id === pic.id){
            if(picture.isSelected){
               picture.isSelected = false;
               picture.pictureClassName = "picture-div none";
            } else {
               picture.isSelected = true;
               picture.pictureClassName = "picture-div green";
            }

          }
          return picture; 
      ));
}

 render() {
 var changeClass = this.state.pictureClassName;
    var pics = this.state.pics.map(function(pic, i) {
        if (/*something*/) {
            return (
            <div className="pic-div" key={i} >
                <Picture 
                    isSelected={pic.isSelected}
                    pictureClassName={changeClass}
                    onClick={this.handlePictureClick.bind(this, pic)} 
                />
            </div>
            }
        }.bind(this));
    return (
    <div className="Options-container">
        <div className="container">{pics}</div>
    </div>
    );
}

答案 2 :(得分:3)

我认为您应该使用第一个绑定选项。

您的isSelected布尔值由您所有的子图片共享,因此当iselected为true时,它适用于您的所有图片组件。

我成了一个工作小提琴here

class PicturesFetch extends React.Component {
constructor(props) {
super(props);
    this.state = { 
        selected: null,
        pictureClassName: "picture-div green",
        pics : [{name : '1'},{name : '2'},{name : '3'},{name : '4'}]
    };
this.handlePictureClick = this.handlePictureClick.bind(this); /*#1      tested bind*/
}
handlePictureClick (itemSelected){    
console.log(itemSelected)
    this.setState({
        selected: itemSelected,
        pictureClassName: "picture-div green"
    }) 
 }
render() {
   var changeClass = this.state.pictureClassName;
   var selected = this.state.selected;
   var click = this.handlePictureClick;
   var pics = this.state.pics.map((pic, i) => {    
   var itemSelected = selected && selected.name ===       pic.name;
        return (
        <div className="pic-div" key={i} >
            <Picture 
                isSelected={itemSelected}
                pictureClassName={changeClass}
                onClick={click}
                pic={pic}
            />
        </div>
        );
     });
return (
   <div className="Options-container">
      <div className="container">{pics}</div>
   </div>
  )
 }}
class Picture extends React.Component  {
  constructor(props) {
  super(props);     
  }
  render() {
    var pictureClassName = this.props.pictureClassName;
    console.log(this.props.isSelected)
    return (
    <div onClick={ () => this.props.onClick(this.props.pic)}     className={pictureClassName}>
        <h5>{this.props.pic.name}  {this.props.isSelected ? 'selected'    : 'not selected'}</h5>
      </div>
    )
 }}

我希望它对你有所帮助