レンダリング時に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)}

その後、期待どおりに動作します。なぜこれが起こるのですか?

回答:


191

関数へのonClick 参照に渡す必要があります。これactivatePlaylist( .. )を行うには、関数を呼び出してonClick、から返された値に渡しますactivatePlaylist。次の3つのオプションのいずれかを使用できます。

。を使用して.bind

activatePlaylist.bind(this, playlist.playlist_id)

。アロー機能を使用する

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

。または関数を返すactivatePlaylist

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

Reactこの方法の以前のバージョンで機能したことを覚えていません。私は間違ったことを覚えていますか、それともapi変更されましたか?
jhamm

@jhamm ES6クラスを使用しており、この場合は手動でコンテキストをバインドする必要があります。
Alexander T.

@AlexanderT。理解できないことが1つあります。.bindステップ1で言ったように、コンテキストをにバインドする場合、ステップ2を実行する必要がありますか?もしそうなら、なぜですか?アロー関数を使うと、コンテキストは関数が定義された場所だと思いますが、を使ってコンテキストをアタッチしている場合.bind、コンテキストはすでにアタッチされていますよね?
Rafa Romero

2
@Rafa Romeroそれはちょうど3つの異なるオプションです、それらの1つを使用できます
Alexander T.

2
React Docsの公式Webサイトには、この質問に詳細に回答したセクションがあります。reactjs.org
docs

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を渡すことにより、メソッドの参照を作成するために使用されますthisplaylist.playlist_id

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

これにより、ユーザーのクリックアクションでのみトリガーされる関数がonClickイベントにアタッチされます。このコードが実行this.activatePlaylistされると、メソッドが呼び出されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.