0

I'm new to React and I'm having trouble setting state for an array of objects. I want each object to be able to reflect and "clicked" state individually. Below is my code.

const pictures = [
     {
            photo: 'https://cdn.images.dailystar.co.uk/dynamic/1/photos/755000/620x/cristiano-ronaldo-net-worth-how-much-madrid-player-worth-695569.jpg?r=5c053f491050f',
            id: 0,
            clicked: false
        }, {
            photo: 'https://www.tsn.ca/polopoly_fs/1.912227!/fileimage/httpImage/image.jpg_gen/derivatives/landscape_620/antoine-griezmann.jpg',
            id: 1,
            clicked: false
        }, {
            photo: 'https://e00-marca.uecdn.es/assets/multimedia/imagenes/2018/02/03/15176565269601.jpg',
            id: 2,
            clicked: false
        }, {
            photo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqa94bKUtifeRx2kxVEZFgTNx3JjEgD1ymNqRP8k8Au9zmLZiz',
            id: 3,
            clicked: false
        },
]

export default class picRender extends Component {

    state = {
        clicked: false
    }

    handleClick = (event) => {
        if (this.state.clicked === false) {
            this.setState({clicked: true});
            console.log(event.target.getAttribute('data-key') + " state changed to clicked");
            console.log(this.state.clicked);
        } else if (this.state.clicked === true) {
            console.log('THIS HAS BEEN CLICKED!');
        }
    }

    render() {
        return pictures.map(pic => <img
            className="photo"
            data-key={pic.photo}
            key={pic.id}
            src={pic.photo}
            onClick={this
            .handleClick.bind(this)}></img>);
    }
}

Each time one of the pictures is clicked, the entire array's state is changed to "true." I'm not sure how to reflect each individual object's change of state.

1
  • The simple answer is to split img into another component and add on click there, so each item in array would have it's own state Commented Dec 10, 2018 at 17:44

2 Answers 2

1

The reason you are getting just true or false is because currently you are only storing one variable clicked in state. If you want to handle the state for each picture individually you should have an array in state to manage the clicked state for each picture. The simplest way for you to do this would be to just set you initial state to be equal to your pictures array as so

state = {
        pictures: [
     {
        photo: 'https://cdn.images.dailystar.co.uk/dynamic/1/photos/755000/620x/cristiano-ronaldo-net-worth-how-much-madrid-player-worth-695569.jpg?r=5c053f491050f',
        id: 0,
        clicked: false
    }, {
        photo: 'https://www.tsn.ca/polopoly_fs/1.912227!/fileimage/httpImage/image.jpg_gen/derivatives/landscape_620/antoine-griezmann.jpg',
        id: 1,
        clicked: false
    }, {
        photo: 'https://e00-marca.uecdn.es/assets/multimedia/imagenes/2018/02/03/15176565269601.jpg',
        id: 2,
        clicked: false
    }, {
        photo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqa94bKUtifeRx2kxVEZFgTNx3JjEgD1ymNqRP8k8Au9zmLZiz',
        id: 3,
        clicked: false
    },

   ],
 }

now in your click event you need to identify which picture was clicked and then change the clicked state of that particular picture.

One way you might do this would be to pass your image id to the handleClick as so

render() {
        return pictures.map(pic => <img
            className="photo"
            data-key={pic.photo}
            key={pic.id}
            src={pic.photo}
            onClick={this
            .handleClick.bind(this, pic.id)}></img>);
    }

and then in your handleClick just modify the clicked state of the picture whose id is passed in

handleClick = (event, id) => {
        //find the picture using the id and change its clicked state
    }
Sign up to request clarification or add additional context in comments.

Comments

0

First of all, the component names must begin with capital letters? PicRender

In JSX, lower-case tag names are considered to be HTML tags

A simple solution to make an array to have all the clicked id's

const pictures = [
  {
    photo: 'https://cdn.images.dailystar.co.uk/dynamic/1/photos/755000/620x/cristiano-ronaldo-net-worth-how-much-madrid-player-worth-695569.jpg?r=5c053f491050f',
    id: 0,
    clicked: false
  }, {
    photo: 'https://www.tsn.ca/polopoly_fs/1.912227!/fileimage/httpImage/image.jpg_gen/derivatives/landscape_620/antoine-griezmann.jpg',
    id: 1,
    clicked: false
  }, {
    photo: 'https://e00-marca.uecdn.es/assets/multimedia/imagenes/2018/02/03/15176565269601.jpg',
    id: 2,
    clicked: false
  }, {
    photo: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTqa94bKUtifeRx2kxVEZFgTNx3JjEgD1ymNqRP8k8Au9zmLZiz',
    id: 3,
    clicked: false
  },
]

 class PicRender extends React.Component {

  state = {
    clicked: []
  }

  handleClick = (pic) => {
    if(this.state.clicked.indexOf(pic.id) === -1){
      this.setState((prevState) => ({ clicked: [...prevState.clicked, pic.id] })) // added the id to clicked array
    }else{ // remove the id from clicked array
      this.setState((prevState) => ({ clicked: prevState.clicked.filter(row => row !== pic.id) })) 
    }
  }

  render() {
    return pictures.map(pic => <img
      className="photo"
      data-key={pic.photo}
      style={this.state.clicked.indexOf(pic.id) !== -1 ? {border: '5px solid green'} : {}}
      key={pic.id}
      src={pic.photo}
      onClick={this.handleClick.bind(this, pic)}></img>);
  }
}

ReactDOM.render(<PicRender />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='app'></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.