Как установить обработчик событий в подкомпоненте React

StackOverflow https://stackoverflow.com//questions/21010400

Вопрос

У меня возникли проблемы с подключением пунктов меню к обработчику событий.Вот макет пользовательского интерфейса, показывающий изменения состояния с течением времени.Это раскрывающееся меню (через 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>
    )
  }
}
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top