用于覆盖事件处理程序的子类组件?

时间:2017-02-08 10:25:47

标签: javascript reactjs

我有一个复杂的React组件(来自react-widgets的Combobox),并希望改变它的一小部分行为 - 我想覆盖onKeyDown事件。如果输入被按下,我想自己处理它,而Combobox不应该看到按键。除此之外,我希望它能成为替代品。

我知道React强烈建议使用合成而不是继承,但在这种情况下,合成似乎很糟糕 - 如果我创建一个包含Combobox的新组件,我必须将每个道具转发到组合框:

class MyCombobox extends Component {
    render() {
        return (<Combobox data={this.props.data}
                          value={this.props.value}
                          onChanged={this.props.onChanged}
                          ...
                />);
    }
}

我也尝试过只包含一个常规的Combobox,并在其容器中设置onKeyDown,但这并未覆盖该事件 - 原始的Combobox仍然获取该事件,而我的Container也获得了它:

// in MyContainer.render:
return (
    <div className="MyContainer">
        <Combobox data={...} onKeyDown={this.handleKeyDown} />
    </div>
);

这里几乎有效:

class MyCombobox extends Combobox {
  handleKeyDown(event) {
    console.log('MyCombobox.handleKeyDown', event);
    console.log(this);  // this: null!

    if (event.key === 'Enter') {
      event.preventDefault();
      // super.close();  // fails
    }
  }

  render() {
    let result = super.render();
    return React.cloneElement(result, {onKeyDown: this.handleKeyDown});
  }
}

我可以拦截事件并阻止Combobox处理它。但是,thisnull。如果我改为使用handleKeyPress箭头功能,我可以访问this(它是MyCombobox对象),但我无法访问任何Combobox的属性。特别是super.close()不起作用(我在函数或类之外得到“超级”)。

2 个答案:

答案 0 :(得分:0)

我不确定它是否有帮助,但您可以轻松地将所有道具传递给其他组件(使用ES6解包):

<p>line 1 </p>
<p>line 2 বাংলাদেশ আমার দেশ</p>
<p> line 3 </p>
line 4 unwrapped
<p> line 5 </p>
<p>line 6 বাংলাদেশ আমার দেশ</p>

我认为它可以帮助您使用合成来解决您的问题。

答案 1 :(得分:0)

所以,这种作品,似乎是做反应方式(构图,只通过道具传递信息给儿童)。

它的作用是,当我输入自定义文本并按回车键时,它会接收该文本并关闭菜单,而不是丢弃文本并选择列表中的某些元素。

它仍然不像原生组合框那样100%,所以我现在放弃并尝试不同的组件:-)。但对于试图“子类化”组件的其他人来说,这可能是一个有用的解决方法。

您可以简化这一点,我不确定是否需要手动处理value

class MyCombobox extends Component {
  handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      event.preventDefault();
      this.setState({open: false, value: event.target.value});
    }
  }

  constructor() {
    super();
    this.state = {open: false, value: null};
  }

  render() {
    return (
      <Combobox value={this.state.value} open={this.state.open}
      onToggle={(isOpen)=>this.setState({open:isOpen})}
      onChange={(newValue)=>this.setState({value:newValue})}
      onKeyDown={this.handleKeyDown} {...this.props} />
    );
  }
}