1

In my frontend Reactjs app, I upload multiple images at the same time and save the urls in an array. When trying to loop an array which contains url to display on website, it shows each image in a separate box (which is good). However, when I click on a single image, it renders all the image urls in the array as per console log.

When I click a single image this shows up in console log:

http://192.168.22.124:3000/source/5102018114022AM-pexels-photo.jpg http://192.168.22.124:3000/source/5102018114022AM-redhat.jpg

handleClick() {
    this.setState({ isToggleOn: !this.state.isToggleOn})
}

render() {
const { name, fileExt, pic } = this.state;
var img = [];
for (var i = 0; i < pic.length; i++) {
  console.log(pic[i]);
    img.push(<a style={{width: 200, height: 250}} key={i} className={'tc ' + change + ' dib br3 ma2 pa2 grow bw2 shadow-5'} onClick={this.handleClick}>
      <div key={i}>
      <img style={{width: 175, height: 175}} className='tc br3' alt='robots' key={i} src={`${pic[i]}`}/>
      </div>
      </a>)
};

  return (
    isToggleOn && fileExt !== 'mp4' ?
    <div>
    { img }
    </div>
1
  • can you show the handleClick function? Commented May 10, 2018 at 7:09

1 Answer 1

1

Right now you are console.loging inside the loop in your render function. So whenever the content is rerendered, it will loop through and console.log multiple times. Because your handleClick method is calling setState, the component will be rerendered, which calls the render() function again and then console.log in the loop.

It sounds like what you want is it to only console.log the item you click on. If that's the case, then you would put your console.log inside the handleClick method which you would pass the parameter to:

onClick={() => this.handleClick(p)}

Also a much better way to do this is to use .map like below:

handleClick(url) {
  console.log(url);
  this.setState({ isToggleOn: !this.state.isToggleOn});
}

render() {
  const { name, pic } = this.state;
  return (
    <div>
      {pic.map((p, i) => (
        <a style={{width: 200, height: 250}} key={p} className={'tc ' + change + ' dib br3 ma2 pa2 grow bw2 shadow-5'} onClick={() => this.handleClick(p)}>
          <div>
            <img style={{width: 175, height: 175}} className='tc br3' alt='robots' src={p}/>
            <h2 style={{position: "absolute", top: 185, bottom: 0, right: 0, left: 0}} className='f6 measure-narrow lh-copy'>{name[i]}</h2>
          </div>
        </a>
      ))}
    </div>
  );
}

Also note: you only need key= on the outer element inside a loop.

Sign up to request clarification or add additional context in comments.

9 Comments

Now console log is also showing this: Proxy {dispatchConfig: {…}, _targetInst: FiberNode, isDefaultPrevented: ƒ, isPropagationStopped: ƒ, _dispatchListeners: ƒ, …}
@TedKhi Check to make sure the onClick passes the parameter using an arrow function: onClick={() => this.handleClick(p)}
I am using arrow function and was still getting that Proxy message. I have updated my question. this.handleClick() is already doing something. So I have to call a separate function for logging the url and it works.. onClick={() => { this.handleClick(); this.urlLog(p);}}
I have one more question. if I have another array called 'name' which contains names for each files. How can I loop for it inside pic map loop so each file has its name displayed. .... <h2 style={{position: "absolute", top: 185, bottom: 0, right: 0, left: 0}} className='f6 measure-narrow lh-copy'>{name}</h2> ...........
list = [ { url: 'www.1.com', name: 'alex' }, { url: 'www.2.com', name: 'tim' } ]; then you would do something like list.map((item) => console.log(item.url, item.name));
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.