为什么onClick会多次触发

时间:2018-04-04 08:54:53

标签: javascript reactjs redux react-router react-router-dom

我正在使用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次。为什么会这样?

5 个答案:

答案 0 :(得分:3)

因为你立即调用方法,所以你应该只处理onClick属性:

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

答案 1 :(得分:1)

因为你不应该立即在onClick道具上调用它。使用这个

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

最终发生的事情是,每当状态发生变化时调用render函数时都会调用onNavBarItemCLick

答案 2 :(得分:1)

<强>解决方案

您需要替换

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在重新渲染方面非常有效,因此它应该发生的事情。

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

答案 3 :(得分:1)

<MyComponent onClick={this.handleClick()} /> 道具有一个函数作为值,所以这里有什么问题?

this.handleClick()

使用onClick立即调用该函数并将其返回值提供给onClick。你想要的是将函数本身赋予<MyComponent onClick={this.handleClick} /> ,如此

this.handleClick

但如果this使用this,则可能会出现另一个错误,因为它不会自动绑定到React类中。有一些方法可以解决这个问题,例如在构造函数中绑定handleClick,使用this的数组函数或在将函数传递给onClick时直接绑定<MyComponent onClick={this.handleClick.bind(this)} />

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()} /> } } 中返回一个函数,这里完全没用。这只是为了说明:

{{1}}

我希望这会有所帮助

答案 4 :(得分:0)

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

所以在上面这段代码中,当你执行onClick = {this.onNavBarItemClick()}时,函数会在那里被调用,而无需用户点击它。如果你执行onClick = {this.onNavBarItemCLick},那么只有在你点击它时才会调用该函数。

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

因此,您可以执行onClick = {this.onNavBarItemClick}onClick = {()=> this.onNavBarItemClick()}