user1072337 user1072337 - 2 months ago 12
React JSX Question

React.js onClick not working clicking span icons mapped from json table

I have icons I am mapping from a json table:

<ul className="major-icons">{ icons.map(function(i){
return <li key={i.id}><span className={i.class} id={i.id} data-id={i.data} onClick={this.onClick} onMouseOver={this.onHover}></span></li>

}) }

</ul>

var icons = [

{ data: '0', id: 'p0', class: 'icon style1 major fa-code'},
{ data: '1', id: 'p1', class: 'icon style2 major fa-bolt'},
{ data: '2', id: 'p2', class: 'icon style3 major fa-camera-retro'},
{ data: '3', id: 'p3', class: 'icon style4 major fa-cog'},
{ data: '4', id: 'sochi', class: 'icon style5 major fa-desktop'},
{ data: '5', id: 'decision_trees', class: 'icon style6 major fa-calendar'},

];


I have an event handler:

getInitialState: function() {
return { project_id: 0};
},

onClick: function(event) {
this.setState({ project_id: event.currentTarget.dataset.id });
console.log("hello");
},


Unfortunately, even clicking these span icons, nothing is happening (not even the console.log). What can I do?

Answer

You have a problem with the scope of this inside your map function. The quickest way to fix your code and make sure that this refers to your Component is to 1) pass this as a second argument to map, 2) use an arrow function; or 3) use the bind method. Here is a demo: http://codepen.io/PiotrBerebecki/pen/jraLWZ

I would however review this answer: http://stackoverflow.com/a/38908620/4186037 and consider refactoring the code so that we don't create a copy of the click handler for each item in the array on each re-render.

  1. Pass thisto map method

          <ul className="major-icons">{ icons.map(function(i) {
              return (
                <li key={i.id}>
                      <span className={i.class}
                            id={i.id}
                            data-id={i.data} 
                            onClick={this.onClick} 
                            onMouseOver={this.onHover}>
                        Some text
                      </span>
                </li>
              );
            }, this) }
    -----------^^^^
          </ul>
    
  2. Arrow function

          <ul className="major-icons">{ icons.map((i) => {
    --------------------------------------------------^^
            return (
                <li key={i.id}>
                      <span className={i.class}
                            id={i.id}
                            data-id={i.data} 
                            onClick={this.onClick} 
                            onMouseOver={this.onHover}>
                      </span>
                </li>
              );
            }) }
          </ul>
    
  3. Bind method

          <ul className="major-icons">{ icons.map(function(i) {
            return (
                <li key={i.id}>
                      <span className={i.class}
                            id={i.id}
                            data-id={i.data} 
                            onClick={this.onClick} 
                            onMouseOver={this.onHover}>
                      </span>
                </li>
              );
            }.bind(this)) }
    ---------^^^^^^^^^^
          </ul>
    
Comments