对项目不起作用的React OnClick

jus*_*der 4 javascript reactjs

我有一个react组件,它使用单独的OnClick呈现一个列表项.

为了找出单击了哪个项,处理程序接受一个参数.处理程序确实被调用 - 但无论单击哪个项目 - 控制台始终记录item3(就像单击item3一样).我在这做错了什么?

class Item {
    constructor(props) {
        super(props);
        this.onItemClickHandler = this.onItemClickHandler.bind(this)
    }

    onItemClickHandler (itemName) {
        console.log("Clicked " + itemName)
    }

    render() {
        this.items = ["item1", "item2", "item3"]
        var lis = []
        for (var liName in this.items) {
            var liName2 = this.items[liName]
            console.log("Adding " + this.items[liName])
            lis.push(<li className="item-ListItem" key={this.items[liName]} onClick={() => this.onItemClickHandler(this.items[liName])}><span><a href="#">{this.items[liName]}</a></span></li>)
        }

        return (
          <div className="item">
            <label className="item-Header"><u>items</u></label>
            <ul className="item-List"> 
            {lis}
            </ul>

          </div>
        );
    }
Run Code Online (Sandbox Code Playgroud)

这一行:

onClick={() => this.onItemClickHandler(this.items[liName])}>
Run Code Online (Sandbox Code Playgroud)

似乎是正确的.

Amr*_*bib 6

问题是您没有this.items[liName]正确捕获值,因为当您到达第三项迭代时,onClick处理程序将始终具有this.items[liName]设置为第三项的值.

解决方案是使用闭包来正确捕获值,我编辑了您的代码并在此链接中创建了一个完整的示例

https://codesandbox.io/s/3xrp6k9yvp

下面用解决方案编写示例代码

class App extends Component {
  constructor(props) {
    super(props);
    this.onItemClickHandler = this.onItemClickHandler.bind(this);
  }

  onItemClickHandler(itemName) {
    console.log("Clicked " + itemName);
  }

  render() {
    this.items = ["item1", "item2", "item3"];
    var lis = [];
    for (var liName in this.items) {
      var liName2 = this.items[liName];
      console.log("Adding " + this.items[liName]);

      //the clickHandler function here is the solution we created a function that get executed immediately each iteration and return a new function that has the correct value of `this.items[liName]` saved
      var clickHandler = (item => {
        return event => {
          this.onItemClickHandler(item);
        };
      })(this.items[liName]);

      lis.push(
        <li
          className="item-ListItem"
          key={this.items[liName]}
          onClick={clickHandler} // here we use the clickHandler function directly
        >
          <span>
            <a href="#">{this.items[liName]}</a>
          </span>
        </li>
      );
    }

    return (
      <div className="item">
        <label className="item-Header">
          <u>items</u>
        </label>
        <ul className="item-List">{lis}</ul>
      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

有关闭包的更多信息和示例,请检查此链接


编辑我们可以let在ES6 中使用,而不是var在@ArchNoob提到的for循环中使用,因为使用let将使liName块作用域