为什么在渲染时调用我的onClick?-React.js


100

我有一个已创建的组件:

class Create extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    var playlistDOM = this.renderPlaylists(this.props.playlists);
    return (
      <div>
        {playlistDOM}
      </div>
    )
  }

  activatePlaylist(playlistId) {
    debugger;
  }

  renderPlaylists(playlists) {
    return playlists.map(playlist => {
      return <div key={playlist.playlist_id} onClick={this.activatePlaylist(playlist.playlist_id)}>{playlist.playlist_name}</div>
    });
  }
}

function mapStateToProps(state) {
  return {
    playlists: state.playlists
  }
}

export default connect(mapStateToProps)(Create);

当我render这个页面,activatePlaylist被每一个信息playlist在我的map。如果我bind activatePlaylist喜欢:

activatePlaylist.bind(this, playlist.playlist_id)

我还可以使用匿名函数:

onClick={() => this.activatePlaylist(playlist.playlist_id)}

然后它会按预期工作。为什么会这样?

Answers:


191

您需要传递给函数的onClick 引用,当您这样做时,您activatePlaylist( .. )可以调用函数并传递给onClick从返回的值activatePlaylist。您可以使用以下三个选项之一:

1。使用.bind

activatePlaylist.bind(this, playlist.playlist_id)

2。使用箭头功能

onClick={ () => this.activatePlaylist(playlist.playlist_id) }

3。或从返回函数activatePlaylist

activatePlaylist(playlistId) {
  return function () {
     // you code 
  }
}

我不记得它在React这种方式的早期版本中可以工作。我是否记错了或已api更改?
jhamm 2015年

@jhamm您正在使用ES6类,在这种情况下,您应该手动绑定上下文。
亚历山大·

@AlexanderT。有一件我不明白的事情。如果您将上下文与绑定.bind,如您在步骤1中所述,是否有必要执行步骤2?如果是的话,为什么呢?因为我认为使用箭头函数时,上下文是定义函数的地方,但是如果我们使用附加上下文.bind,那么上下文已经附加了,对吗?
拉法·罗梅罗

2
@Rafa Romero这只是三个不同的选项,您可以使用其中一个
Alexander

2
现在,官方的React Docs网站上有一个部分全面解答了这个问题:reactjs.org/docs/faq-functions.html
zenoh

2

当React宣布发布基于类的组件时,就记录了这种行为。

https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html

自动绑定

React.createClass具有内置的魔术功能,可以自动为您绑定所有方法。对于不习惯在其他类中使用此功能的JavaScript开发人员来说,这可能会有些混乱,或者当他们从React转到其他类时,可能会造成混乱。

因此,我们决定不将其内置在React的类模型中。如果需要,您仍然可以在构造函数中显式预绑定方法。


2

我知道这篇文章已经有几年历史了,但是只是为了参考来自https://reactjs.org/tutorial/tutorial.html的关于这个常见错误的最新React教程/文档(我也是这样做的):

注意

为了节省类型并避免这种行为的混淆,我们将在此处以及下文中将箭头函数语法用于事件处理程序:

class Square extends React.Component {
 render() {
   return (
     <button className="square" onClick={() => alert('click')}>
       {this.props.value}
     </button>
   );
 }
}

请注意,如何使用onClick = {()=> alert('click')},将函数作为onClick道具传递。单击后,React只会调用此函数。忘记()=>并编写onClick = {alert('click')}是一个常见错误,每次组件重新渲染时都会触发警报。


1

您传递方法的方式this.activatePlaylist(playlist.playlist_id),将立即调用该方法。您应该将方法的引用传递给onClick事件。请按照下面提到的一种实现来解决您的问题。

1。
onClick={this.activatePlaylist.bind(this,playlist.playlist_id)}

在这里,bind属性用于this.activatePlaylist通过传递this上下文和参数来创建方法的引用playlist.playlist_id

2。
onClick={ (event) => { this.activatePlaylist.(playlist.playlist_id)}}

这会将一个函数附加到onClick事件,该事件仅在用户单击操作时触发。执行此代码时,this.activatePlaylist将调用该方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.