Подтвердить что ты не робот

ReactJS: обработчик onClick не срабатывает при размещении на дочернем компоненте

Недавно я начал работать с ReactJS. В частности, я использую компоненты react-rails ruby ​​gem и react-bootstrap.

У меня вопрос о размещении onClick прослушивателей событий в дочерних компонентах.

Как видно из примера кода ниже, у меня есть родительский компонент, который "вызывает" дочерний компонент в своей функции render. Внутри этой функции render у меня есть React onClick listener, который вызывает handleToggle при нажатии.

###* @jsx React.DOM ###

ToggleIconButton = React.createClass
  getInitialState: ->
    toggleOn: false
  handleToggle: (evt) ->
    this.setState(toggleOn: !this.state.toggleOn)
  render: ->
    `<IconButton onClick={this.handleToggle}>Toggle Button</IconButton>`

IconButton = React.createClass
  render: ->
    # BsButton and BsGlyphicon are React-Bootstrap components
    `<BsButton>
      <BsGlyphicon glyph={this.props.glyph} />
      {" " + this.props.text}
     </BsButton>`

К сожалению, это не работает так, как я думал. ToggleIconButton::handleToggle никогда не вызывается. Вместо этого слушатель onClick размещается на IconButton и ссылается на ToggleIconButton::handleToggle.

React Dev Tool Screen


Я не хочу добавлять никаких дополнительных действий в IconButton. Как я вижу это, условная логика не должна быть помещена в IconButton. Все, что он должен делать, это значок и кнопка, и не нужно беспокоиться о каких-либо событиях в браузере. Это для ToggleIconButton.

Хотя я знаю, что могу обернуть React Div вокруг IconButton и написать там прослушиватель onClick (я пробовал это, и он работает), похоже, что это немного болтливо.

Кто-нибудь знает хороший способ сделать это? Спасибо, ребята!

4b9b3361

Ответ 1

Таким образом, надлежащим способом обработки событий в этом случае было бы передать обработчик события дочернему компоненту. Есть несколько способов выполнить то, что вы хотите, и я мог бы реализовать это поведение по-разному (не уверен, что такое вариант использования), но я подключил пример JSX для вас, который демонстрирует типичную обработку событий между родительскими и дочерними компонентами. Вы можете найти его здесь...

JS Fiddle

Просто подумайте об этом так:

var ParentComponent = React.createClass({
    render: function(){
        return (
            <ChildComponent onSomeEvent={this.handleThatEvent} />;
        )
    },
    handleThatEvent: function(e){
         //update state, etc.
    }
});

var ChildComponent = React.createClass({
    render: function(){
        return (
           <input type="button" onClick={this.props.onSomeEvent} value="Click Me!" />
        )
    }
});

Ответ 2

Вам не нужно создавать дочерний компонент, если перед вызовом node вы создаете var для ссылки на рендеринг, это i.e.

var self = this;

Итак, например (это надуманно, и var self не требуется в этом случае, но в случае вложенных операторов return потребуется).

var ParentComponent = React.createClass({
    render: function(){
        var self = this;
        return (
            <input type="button" onClick={self.handleThatEvent} value="Click Me!" />;
        )
    },
    handleThatEvent: function(e){
         //update state, etc.
    }
});

Еще лучше, вы можете привязать это к функции.

var ParentComponent = React.createClass({
    render: function(){
        return (
            this.state.array.map(function(){
              return (<input type="button" onClick={this.handleThatEvent} value="Click Me!" />);
            }.bind(this));
        )
    },
    handleThatEvent: function(e){
         //update state, etc.
    }
});

Или следить за предложением предложения в комментариях

var ParentComponent = React.createClass({
    render: function(){
        return (
            this.state.array.map(function(){
              return (<input type="button" onClick={this.handleThatEvent} value="Click Me!" />);
            }, this);
        )
    },
    handleThatEvent: function(e){
         //update state, etc.
    }
});