Socrates
Socrates

Reputation: 9574

JavaScript React event gets weirdly fired

I am trying to create a HTML list using React. All works well, but I get some weird behaviour with the click event I assign to the <li>-tag. Here are two codes of which one works, but not the other.

The difference between both codes is the way I assign the onClick-event to the <li>-tag.

Within the not working code I tell the onMenuClick function which area I am speaking of. When loading the page, I get this method fired three times.

Within the working code I do not provide any arguments for the onMenuClick function. Here though I am not able to know which <li>-tag fired the event. I need to know it though, because I want to react on it.

Why is the event firing three times in the not working code?

Not working code:

var React = require('react');

var Application = React.createClass({
  onMenuClick: function(area) {
    console.log('Application.onMenuClick(' + area + ')');
  },

  render: function () {
    var classWideThis = this;

    var areas = [
      { "id": 0, "name": "Bidirektional" },
      { "id": 1, "name": "Schleifen" },
      { "id": 2, "name": "Events" }
    ];

    return (
      <div>
        <h1>ReactJS Prototyp</h1>
        <div className="menuWindow topAbstand">
          <ul className="menuUl">
            {areas.map(function(area) {
              return <li className="menuLi"
                         key={area.id}
                         onClick={classWideThis.onMenuClick(area.name)}>
                       {area.name}
                     </li>
            })}
          </ul>
        </div>
      </div>
    );
  }
});

module.exports = Application;

Good working code:

var React = require('react');

var Application = React.createClass({
  onMenuClick: function() {
    console.log('Application.onMenuClick()');
  },

  render: function () {
    var classWideThis = this;

    var areas = [
      { "id": 0, "name": "Bidirektional" },
      { "id": 1, "name": "Schleifen" },
      { "id": 2, "name": "Events" }
    ];

    return (
      <div>
        <h1>ReactJS Prototyp</h1>
        <div className="menuWindow topAbstand">
          <ul className="menuUl">
            {areas.map(function(area) {
              return <li className="menuLi"
                         key={area.id}
                         onClick={classWideThis.onMenuClick}>
                       {area.name}
                     </li>
            })}
          </ul>
        </div>
      </div>
    );
  }
});

module.exports = Application;

Upvotes: 1

Views: 131

Answers (1)

madox2
madox2

Reputation: 51841

onClick prop expect function to be passed. You call onMenuClick function and pass it's result as the property in the first example. You can change onMenuClick function to return function which handles click event and use closure to remember passed parameter:

onMenuClick: function(area) {
    return function() {
        console.log('Application.onMenuClick(' + area + ')');
    };
},

and then pass it to onClick:

onClick={classWideThis.onMenuClick(area.name)}

More advanced (but better looking) would be to bind original onMenuClick function to the correct context and prepend parameters to it:

onClick={classWideThis.onMenuClick.bind(classWideThis, aera.name)}

Upvotes: 2

Related Questions