OnClick'im oluşturma sırasında neden çağrılıyor? - React.js


106

Oluşturduğum bir bileşenim var:

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);

Ne zaman renderbu sayfayı, activatePlaylisther biri için çağrılır playlistskinTenimde map. Ben ise bind activatePlaylistister:

activatePlaylist.bind(this, playlist.playlist_id)

Anonim bir işlevi de kullanabilirim:

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

daha sonra beklendiği gibi çalışır. Bu neden oluyor?

Yanıtlar:


199

Sen geçmek gerek onClick referans böyle yaptığınızda, işlevine activatePlaylist( .. )işlevi çağırmak ve geçmek onClickdöndürülen değeri activatePlaylist. Bu üç seçenekten birini kullanabilirsiniz:

1 . kullanma.bind

activatePlaylist.bind(this, playlist.playlist_id)

2 . ok işlevini kullanarak

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

3 . veya geri dönüş işleviactivatePlaylist

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

ReactBu şekilde önceki versiyonlarda çalıştığını hatırlamıyorum . Yanlış mı hatırlıyorum yoksa apideğişti mi?
jhamm

@jhamm ES6 sınıflarını kullanıyorsunuz ve bu durumda bağlamı manuel olarak bağlamalısınız.
Oleksandr T.

@AlexanderT. anlamadığım bir şey var. .bind1. adımda söylediğiniz gibi bağlamı ile bağlarsanız, 2. adımı yapmak gerekir? ve eğer öyleyse, neden? Çünkü ok işlevini kullandığınızda, bağlamın işlevin tanımlandığı yer olduğunu düşünüyorum, ancak bağlamı kullanarak ekliyorsak, bağlam .bindzaten eklenmiştir, değil mi?
Rafa Romero

2
@Rafa Romero, sadece üç farklı seçenek, bunlardan birini kullanabilirsiniz
Oleksandr T.

2
Artık resmi React Docs web sitesinde bu soruyu tam olarak yanıtlayan bir bölüm var: reactjs.org/docs/faq-functions.html
zenoh

2

Bu davranış, React sınıf tabanlı bileşenlerin piyasaya sürüldüğünü duyurduğunda belgelenmiştir.

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

Otomatik bağlama

React.createClass, tüm yöntemleri sizin için otomatik olarak buna bağlayan yerleşik bir sihirli özelliğe sahiptir. Bu, diğer sınıflarda bu özelliğe alışkın olmayan JavaScript geliştiricileri için biraz kafa karıştırıcı olabilir veya React'ten diğer sınıflara geçtiklerinde kafa karıştırıcı olabilir.

Bu nedenle, bu yerleşik ürünü React'in sınıf modeline yerleştirmemeye karar verdik. Yine de isterseniz yapıcınızda yöntemleri açıkça önceden bağlayabilirsiniz.


2

Bu gönderinin zaten birkaç yıllık olduğunu biliyorum, ancak bu yaygın hata hakkındaki en son React eğitimine / belgelerine (ben de yaptım) https://reactjs.org/tutorial/tutorial.html adresinden referans vermek için :

Not

Yazmayı kaydetmek ve bunun kafa karıştırıcı davranışını önlemek için, burada ve aşağıda olay işleyicileri için ok işlevi sözdizimini kullanacağız:

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

OnClick = {() => alert ('click')} ile, onClick prop olarak bir işlevi aktardığımıza dikkat edin. React, bu işlevi yalnızca bir tıklamadan sonra çağırır. Unutma () => ve onClick = {alert ('click')} yazmak yaygın bir hatadır ve bileşen her yeniden oluşturulduğunda uyarıyı tetikler.


1

Yöntemi geçirme şekliniz this.activatePlaylist(playlist.playlist_id), yöntemi hemen çağıracaktır. Yöntemin referansını onClicketkinliğe iletmelisiniz. Sorununuzu çözmek için aşağıda belirtilen uygulamalardan birini izleyin.

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

Burada bağlama özelliği, bağlamı ve bağımsız değişkeni this.activatePlaylistileterek yöntemin bir başvurusunu oluşturmak için kullanılır.thisplaylist.playlist_id

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

Bu, onClick olayına yalnızca kullanıcı tıklama eyleminde tetiklenecek bir işlev ekleyecektir. Bu kod ortaya çıktığında this.activatePlaylistyöntem çağrılacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.