为什么 onClick 会触发多次

Why onClick fires several times

我正在使用 Semantic-ui-react reduxreact-router-dom。在我的组件中,我有导航栏:

<Menu >     
  <Menu.Item as={Link} to="/" onClick = {this.onNavBarItemCLick()}>
    home
  </Menu.Item>

  <Menu.Item as={Link} to="profile" onClick = {this.onNavBarItemCLick()}>
    profile
  </Menu.Item>

  <Menu.Item as={Link} to="shop" onClick = {this.onNavBarItemCLick()}>
    shop
  </Menu.Item>
</Menu>

如果我点击其中一个导航项方法 onNavBarItemClick 会触发 3 次。为什么会这样?

因为你不应该在 onClick 属性中立即调用它。使用这个

<Menu.Item as={Link} to="/" onClick = {this.onNavBarItemCLick}>

最后发生了什么,当状态改变时每次调用渲染函数时都会调用 onNavBarItemCLick

因为您立即调用方法,所以您应该只将处理程序传递给 onClick 属性:

as={Link} to="shop" onClick = {this.onNavBarItemCLick.bind(this)}>

解决方案

你需要更换

onClick = {this.onNavBarItemCLick()}

onClick = {() => this.onNavBarItemCLick()}  // perserving class's this

或者如果您更喜欢绑定符号

onClick = {this.onNavBarItemCLick.bind(this)} // perserving class's this

其他

onClick = {this.onNavBarItemCLick} // not perserving class's this

为什么会这样

发生这种情况是因为当您单击时 render() 会再次调用。 React 在 re-rendering 中非常高效,所以这是它应该发生的事情。

您的实施存在问题,您没有传递方法引用,而是传递了此类方法的返回值。

onClick 属性将一个函数作为值,所以这里有什么问题?

<MyComponent onClick={this.handleClick()} />

使用 this.handleClick() 立即调用该函数并将其 return 值赋给 onClick。您在这里想要的是像这样

将函数本身提供给 onClick
<MyComponent onClick={this.handleClick} />

但是如果 this.handleClick 使用 this 你可能会在那里遇到另一个错误,因为它不会自动绑定在 React class 中。有一些方法可以解决这个问题,比如在构造函数中绑定 this,为 handleClick 使用数组函数,或者在将函数传递给 onClick 时直接绑定 this,例如

<MyComponent onClick={this.handleClick.bind(this)} />

更进一步,您还可以 return handleClick 中的一个函数,这里完全没用。这只是为了说明:

class MyComponent extends React.Component {
  handleClick () {
    return () => { console.log('I am triggered on click') }
  }

  render () {
    // We call this.handleClick() which returns the function
    // that'll be actually called on click.
    return <div onClick={this.handleClick()} />
  }
}

希望对您有所帮助

当您执行 this.onNavBarItemClick() 时,括号会在该点执行函数。而 this.onNavBarItemClick 会将其视为变量。

所以在上面的代码中,当您执行 onClick = {this.onNavBarItemClick()} 时,该函数会在用户点击它的情况下自行调用。而如果您执行 onClick = {this.onNavBarItemCLick},则只有在您单击它时才会调用该函数。

你也可以onClick = {()=>this.onNavBarItemClick()}。通过这样做,您正在创建一个匿名函数并将其传递给 onClick.

所以您可以选择 onClick = {this.onNavBarItemClick}onClick = {()=> this.onNavBarItemClick()}