Как установить обработчик событий в подкомпоненте React
-
21-12-2019 - |
Вопрос
У меня возникли проблемы с подключением пунктов меню к обработчику событий.Вот макет пользовательского интерфейса, показывающий изменения состояния с течением времени.Это раскрывающееся меню (через Bootstrap), в котором элемент корневого меню показывает текущий выбор:
[ANN]<click ... [ANN] ... [BOB]<click ... [BOB]
[Ann] [Ann]
[Bob]<click + ajax [Bob]
[Cal] [Cal]
Конечная цель — асинхронно изменить содержимое страницы на основе выбора пользователя.Нажатие на Боба должно вызвать handleClick
, но это не так.
В качестве примечания: меня не очень устраивает способ вызова компонентDidMount. this.handleClick();
, но на данный момент он работает как способ получить начальное содержимое меню с сервера.
/** @jsx React.DOM */
var CurrentSelection = React.createClass({
componentDidMount: function() {
this.handleClick();
},
handleClick: function(event) {
alert('clicked');
// Ajax details ommitted since we never get here via onClick
},
getInitialState: function() {
return {title: "Loading items...", items: []};
},
render: function() {
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
});
return <ul className='nav'>
<li className='dropdown'>
<a href='#' className='dropdown-toggle' data-toggle='dropdown'>{this.state.title}</a>
<ul className='dropdown-menu'>{itemNodes}</ul>
</li>
</ul>;
}
});
$(document).ready(function() {
React.renderComponent(
CurrentSelection(),
document.getElementById('item-selection')
);
});
Я почти уверен, что виновато мое смутное понимание области видимости javascript, но все, что я пробовал до сих пор, потерпело неудачу (включая попытку передать обработчик через реквизит).
Решение
Проблема в том, что вы создаете узлы элементов, используя анонимную функцию, и внутри нее this
означает window
.Исправление состоит в том, чтобы добавить .bind(this)
к анонимной функции.
var itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={this.handleClick}>{item}</a></li>;
}.bind(this));
Или создайте копию this
и используйте это вместо этого:
var _this = this, itemNodes = this.state.items.map(function (item) {
return <li key={item}><a href='#' onClick={_this.handleClick}>{item}</a></li>;
})
Другие советы
Как я могу понять спецификацию задачи для «Анны», «Боб», «Cal, решение может быть следующим (на основе компонента React и ES6):
Базовая живая демонстрация здесь
import React, { Component } from "react"
export default class CurrentSelection extends Component {
constructor() {
super()
this.state = {
index: 0
}
this.list = ["Anna", "Bob", "Cal"]
}
listLi = list => {
return list.map((item, index) => (
<li key={index}>
<a
name={item}
href="#"
onClick={e => this.onEvent(e, index)}
>
{item}
</a>
</li>
))
}
onEvent = (e, index) => {
console.info("CurrentSelection->onEvent()", { [e.target.name]: index })
this.setState({ index })
}
getCurrentSelection = () => {
const { index } = this.state
return this.list[index]
}
render() {
return (
<div>
<ul>{this.listLi(this.list)}</ul>
<div>{this.getCurrentSelection()}</div>
</div>
)
}
}
.