The onClick binding for each component in the .map () function

I have a parent component PicturesFetchthat displays another (child) component Picture, which displays a div with an image inside. Now for rendering Picture, it PicturesFetchpasses through the object (pics), and using the .map () function creates several divs with images inside. I want to be able to change the state of each item created separately. Here is what I have tried so far, verified bindings were checked one by one, and not all together:

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" undefined.

onClick, ? , ? .

+4
3

# 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>
        );
}
+3

, @dulwalanise, . this.handlePictureClick undefined, 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

, .

Your isSelected boolean is used by your entire child image, so when true is selected, it is intended for your entire image component.

I made a working script 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>
    )
 }}

I hope this helps you

+2
source

Source: https://habr.com/ru/post/1661913/


All Articles