1

I have an image gallery where I loop trough image objects and I want to pass the i to my onClick function. This is my image gallery code:

<div className="gallery clearfix">
  { block.gallery.map((item, i) => (
    i < 1 ?
     <div className="gallery-image" key={i} onClick={this.toggle}>
       <a href='' className="inner">
          <img src={item.images.thumbnail_sm} alt={block.title} srcSet={`${item.images.thumbnail_md} 1x, ${item.images.thumbnail_lg} 2x`} className="img-fluid image"/>
       </a>          
     </div>
     : null
     ))}
     <div className="gallery-thumbs">
       <div className="row">
        { block.gallery.map((item, i) => (
          i > 0 && i < (limit + 1) ?
          <div className="gallery-item" key={i} onClick={this.toggle}>
          <a href='' className="inner">
            <img src={item.images.thumbnail_sm} alt={block.title} srcSet={`${item.images.thumbnail_md} 1x, ${item.images.thumbnail_lg} 2x`} className="img-fluid image" title="" />
              { block.gallery.length > (limit + 1) && i == limit ?
                <div className="img-overlay">
                   <span className="img-indicator">{ block.gallery.length - (limit + 1) }+ <span className="hidden-xs">Foto's</span></span>
                </div>
             : null 
            }
          </a>
        </div>
        : null
        ))}
     </div>
   </div>
</div>

And this is my reactstrap modal where I want to show the image which is clicked:

<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
      <ModalBody>            
        <img src={block.gallery[this.state.clickedImage].item.images.thumbnail_lg}/>
      </ModalBody>
    </Modal>

And here is the toggle function where I want to pass the clickedImage id:

toggle(id) {
    this.setState({
      clickedImage: id,
      modal: !this.state.modal
    });
  }
7
  • You need to either onClick={this.toggle.bind(this, i)}or store data-index={i} on the tag (retrieve with +event.target.dataset.index) Commented Dec 2, 2016 at 13:31
  • @Matt could you give me an example? Commented Dec 2, 2016 at 13:32
  • 2
    Replace onClick={this.toggle} -> onClick={this.toggle.bind(this, i)}. Your toggle is expecting an id as first parameter, but since it's an event handler, it will get an event object as first parameter instead. The bind will change this so toggle receives id, event parameters, but it's a new function per index per render. Commented Dec 2, 2016 at 13:36
  • a bootstrap react example: jsfiddle.net/free_soul/2ub6rmkc Commented Dec 2, 2016 at 13:39
  • @Matt that is not working ` core.js:119 error TypeError: Cannot read property 'item' of undefined(…)` Commented Dec 2, 2016 at 13:59

1 Answer 1

2

For best practice, I don't suggest binding within onClick, that cause it invoke bind every time when it's clicked. if you are using ES6, instead you should bind it in constructor:

Class MyComponent extends React.Component {
  constructor(props){
    super(props);
    this.toggle = this.toggle.bind(this);
  }
}

and

<div className="gallery-item" key={i} onClick={(i) => this.toggle(i)}></div>

UPDATE: like comments say. this is actually is not the best way, the best way is not to create new function and attach events with every render, which means it should be just

<div className="gallery-item" key={i} onClick={this.toggle}></div>

but since you need to pass the id, the best bet would be refactor it into smaller components like <GalleryItem> and pass the id by props

Worth to read: this

UPDATE: Also please look at comments, using dataset.index and data-index is even better

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

5 Comments

This is equally bad, (i) => this.toggle(i) is a new bind/function for every index and render.
@Kossel: Use onClick={this.toggle} just like that.
that's true. but since he need to pass argument to the toggle function, in order to have only this.toggle means he either has to refactor gallery-item to smaller component or having something flux to dispatch the id for him, or use something outside of es6 or es7
@Kossel or just data-index={i} on the tag and +e.target.dataset.index in the event handler
@Kossel it should be e.currentTarget.dataset.index

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.