【问题标题】:ReactJS: onClick handler not firing when placed on a child componentReactJS:onClick处理程序放置在子组件上时不会触发
【发布时间】:2014-07-28 23:27:55
【问题描述】:

我最近开始使用ReactJS。具体来说,我正在使用react-rails ruby​​ gem 和react-bootstrap 组件。

我有一个关于在子组件中放置onClick 事件侦听器的问题。

从下面的代码示例中可以看出,我有一个父组件,它在其render 函数中“调用”一个子组件。在 render 函数中,我有 React onClick 监听器,当它被点击时会调用 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


我不想向IconButton 添加任何其他行为。在我看来,没有条件逻辑应该放在IconButton 中。它应该做的只是代表一个图标和按钮,而不必担心任何浏览器事件。这就是ToggleIconButton 的用途。

虽然我知道我可以在 IconButton 周围包裹一个 React Div 并在那里写一个 onClick 监听器(我已经尝试过并且它有效),但这似乎有点笨拙。

有人知道这样做的好方法吗?谢谢大家!

【问题讨论】:

标签: reactjs react-jsx


【解决方案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!" />
        )
    }
});

【讨论】:

  • 谢谢帽子。正如您从原始帖子中看到的那样,我确实安装了 ReactJS 开发工具 :)。虽然我知道在我的子组件中我可以添加一个onClick 侦听器,该侦听器将从子组件的props 调用一个函数,但似乎我不应该这样做......如果子组件不应该怎么办?在其他情况下一定要有一个 onClick 监听器吗?如果我想在不同的父组件中使用这个组件但没有 onClick 监听器怎么办?这不会损害组件的可重用性吗?如果这没有意义,请告诉我。
  • 您说得对,先生,我忽略了这一点 :) 所以,您可以做的是将该组件包装在一个 div 中,并为该 div 注册 onClick 以获得您想要的功能而不会造成污染具有该行为的 ChildComponent。类似于
  • 另外,如果没有将该事件明确传递给 ChildComponent,您就不能准确地调用 onClick,因为 Component 本身并不是真正的 HTML 元素,因此没有为它定义 onClick。
  • 谢谢!拯救我的一天! :D 不用说,必须注意绑定父组件以获得正确的范围和行为。
  • 哇,谢谢!真的很有帮助:)
【解决方案2】:

如果在调用节点之前创建一个 var 来引用渲染的 this 即

,则不需要创建子组件
var self = this;

例如(这是人为设计的,在这种情况下不需要 var self,但在嵌套返回语句的情况下则需要)。

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

更好的是,您可以将 this 绑定到函数。

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

或者在 cmets 中遵循 captray 的建议

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

【讨论】:

  • handleThatEvent 的作用域是什么?会有孩子道具还是父母道具?
  • 试试看。但根据绑定,它将是父母。
  • 太好了,感谢这个解决方案在您有多个退货时有效(在我的情况下为 3 个)
  • 提醒一下,对于那些希望在这种情况下使用绑定的人... 许多函数调用(如 map 和 filter)接受第二个参数,它与 bind 做同样的事情,它设置执行上下文到传入的内容,所以你可以调用 .map(function(item) { //do stuff }, this);
  • 这太棒了!我是 React 的新手,只是将我的应用程序重构为更简单、更优雅……花了一天时间试图弄清楚为什么一些嵌套的 child^parent 调用被破坏了。这(不是双关语)解决了所有问题!
猜你喜欢
  • 2019-09-21
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 2021-01-12
  • 1970-01-01
  • 2018-04-30
相关资源
最近更新 更多