0

I am mapping an array in react render. There are multiple DOMs beings rendered.

And each DOM is bound with a click event handler. Which show some details on click.

I want to trigger an auto click on the last element of that array and pass that event to clickHandler.

{
    historyData.map((heading, index) => {
        return(
            <div className="history-node-container" key={index}>
              //This is where click handler is being called.
              <div className="history-node" onClick={(e) => {this.handleHistoryClick(e)}}>
                <span className="history-title">{heading.action}</span>
                <input type="hidden" value={heading.comment} className="comment-hidden" />
                <input type="hidden" value={heading.by} className="comment-by-hidden" />
                <input type="hidden" value={heading.role} className="comment-role-hidden" />
                <input type="hidden" value={heading.added_at} className="comment-added-hidden" />
                <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
              </div>
            </div>
        )
    })
}

And clickHandler Code is:

handleHistoryClick(event){
      event.stopPropagation();
      //Some Code To Display Information Using "event"
}

Now I want to do is if in mapping The element is last one I want to trigger auto click and display it's information accordingly.

How would I achieve that?

Sunny Jangid
  • 578
  • 4
  • 19
Noman Ali
  • 3,160
  • 10
  • 43
  • 77

4 Answers4

1

The map function has a third argument which is the original array on which map was called. You can use that to determine if this is the last one.

{
historyData.map((heading, index, array) => {
  if(index===array.length-1){
    //do something
  }
  return(...)
anand
  • 565
  • 2
  • 9
  • Finding out last element and auto triggering event for that element. What about auto trigger? – Noman Ali Oct 24 '17 at 07:13
  • I was wondering what you want to do inside the event handler. In particular, if you don't need to use the callback argument 'event', you can just call it directly within the if block. or use what hannad-rehman has suggested. Also, are you expecting further user clicks on the last element, after it is auto-triggered – anand Oct 24 '17 at 07:22
0

this may not be the best answer but it will do the trick

 {
        historyData.map((heading, index,originalArr) => {
            return(
                <div className="history-node-container" key={index}>
                  //This is where click handler is being called.
                  <div className="history-node" onClick={ (index==originalArr.length-1)?this.handleHistoryClick(e) : (e) => {this.handleHistoryClick(e)}}>
                    <span className="history-title">{heading.action}</span>
                    <input type="hidden" value={heading.comment} className="comment-hidden" />
                    <input type="hidden" value={heading.by} className="comment-by-hidden" />
                    <input type="hidden" value={heading.role} className="comment-role-hidden" />
                    <input type="hidden" value={heading.added_at} className="comment-added-hidden" />
                    <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
                  </div>
                </div>
            )
        })
    }

this does the trick. you want to check if the current itration is the last iteration. if its the last itration. directly call the function.

onClick={ (index==originalArr.length-1) ? this.handleHistoryClick(e) : (e) => {this.handleHistoryClick(e)}}

hannad rehman
  • 4,133
  • 3
  • 33
  • 55
0

add array in your map arguments:

historyData.map(heading, index, array)

and in your onClick add a condition:

onClick={
 (e) => {
    (index==array.length-1) ? 
       (this.handleHistoryClick(e, true)) : 
       (this.handleHistoryClick(e, false))
  }
}

and in your handler function add a condition too:

handleHistoryClick(event, isLastElement){
      event.stopPropagation();
      if(isLastElement){
         // do somthing
      }else{
         // do somthing else
      }
}
Emad Emami
  • 6,089
  • 3
  • 28
  • 38
0

One should never do anything other than rendering in the render method, especially stuff like event triggers. render has to be pure.

Said that, what could be done is...

  1. first store a ref to the last element in a variable.
  2. trigger the click event in componentDidMount.

Sample code -

{
    historyData.map((heading, index) => {
        return(
            <div className="history-node-container" key={index}>
              // store every item in `this.lastOne`, it will point to the
              // last item at the end of `map` call.
              <div className="history-node" ref={item => this.lastOne = item} onClick={(e) => {this.handleHistoryClick(e)}}>
                <span className="history-title">{heading.action}</span>
                <input type="hidden" value={heading.comment} className="comment-hidden" />
                <input type="hidden" value={heading.by} className="comment-by-hidden" />
                <input type="hidden" value={heading.role} className="comment-role-hidden" />
                <input type="hidden" value={heading.added_at} className="comment-added-hidden" />
                <span className="history-date">{moment(heading.added_at).format("MMMM Do, YYYY")}</span>
              </div>
            </div>
        )
    })
}

And then in componentDidMount -

componentDidMount(){
    if (this.lastOne) {
        this.lastOne.click();
    }
}

If you want to execute the click handler on subsequent updates to the component, put similar code in componentDidUpdate.

hazardous
  • 10,627
  • 2
  • 40
  • 52