#javascript #reactjs
#javascript #reactjs #redux
Вопрос:
У меня есть компонент, который я создал:
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)}
тогда все работает так, как ожидалось. Почему это происходит?
Ответ №1:
Вам нужно передать onClick
ссылку на функцию, когда вы делаете подобным образом, activatePlaylist( .. )
вы вызываете функцию и передаете onClick
значение, возвращенное из activatePlaylist
. Вы можете использовать один из этих трех вариантов:
1. использование .bind
activatePlaylist.bind(this, playlist.playlist_id)
2. использование функции arrow
onClick={ () => this.activatePlaylist(playlist.playlist_id) }
3. или возвращающая функция из activatePlaylist
activatePlaylist(playlistId) {
return function () {
// you code
}
}
Комментарии:
1. Я не помню, чтобы это работало в предыдущих версиях
React
таким образом. Я неправильно помню илиapi
изменилось?2. @jhamm Вы используете классы ES6, и в этом случае вам следует привязать контекст вручную.
3. @AlexanderT. есть одна вещь, которую я не понимаю. Если вы связываете контекст с
.bind
, как вы сказали на шаге 1, необходимо выполнить шаг 2? и если это так, то почему? Потому что я думаю, что когда вы используете функцию arrow, контекст — это тот, в котором была определена функция, но если мы подключаем контекст с помощью.bind
, контекст уже подключен, верно?4. @Rafa Romero это всего лишь три разных варианта, вы можете использовать один из них
5. Теперь на официальном веб-сайте React Docs есть раздел, в котором дан исчерпывающий ответ на этот вопрос: reactjs.org/docs/faq-functions.html
Ответ №2:
Я знаю, что этому сообщению уже несколько лет, но просто чтобы сослаться на последнее руководство / документацию по React об этой распространенной ошибке (я тоже ее допустил) от https://reactjs.org/tutorial/tutorial.html:
Примечание
Чтобы сэкономить на вводе текста и избежать при этом запутанного поведения, мы будем использовать синтаксис функции arrow для обработчиков событий здесь и далее ниже:
class Square extends React.Component {
render() {
return (
<button className="square" onClick={() => alert('click')}>
{this.props.value}
</button>
);
}
}
Обратите внимание, как с помощью onClick={() => alert (‘щелчок’)} мы передаем
функционирует как реквизит onClick. React вызовет эту функцию только после
щелчок. Забыть () => и написать onClick={alert (‘щелчок’)} — это
распространенная ошибка, и будет выдавать предупреждение каждый раз, когда компонент
повторный рендеринг.
Комментарии:
1. Перед ним у меня была функция со стрелкой, подобная этой, и она все еще активировалась.
Ответ №3:
Такое поведение было задокументировано, когда React объявил о выпуске компонентов на основе классов.
https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html
Автоматическая привязка
React.createClass имеет встроенную волшебную функцию, которая автоматически привязывает все методы к этому для вас. Это может немного сбить с толку разработчиков JavaScript, которые не привыкли к этой функции в других классах, или это может сбить с толку при переходе с React на другие классы.
Поэтому мы решили не использовать это встроенное в модель класса React. Вы все еще можете явно предварительно привязать методы в своем конструкторе, если хотите.
Ответ №4:
import React from 'react';
import { Page ,Navbar, Popup} from 'framework7-react';
class AssignmentDashboard extends React.Component {
constructor(props) {
super(props);
this.state = {
}
onSelectList=(ProjectId)=>{
return(
console.log(ProjectId,"projectid")
)
}
render() {
return (
<li key={index} onClick={()=> this.onSelectList(item.ProjectId)}></li>
)}
Комментарии:
1. Не могли бы вы добавить немного объяснений вместо того, чтобы просто публиковать фрагменты кода? Это действительно улучшило бы качество вашего ответа
Ответ №5:
То, как вы передаете метод 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
метод.