【问题标题】:How do I set an event listener on the parent component in ReactJS?如何在 ReactJS 的父组件上设置事件监听器?
【发布时间】:2019-08-19 19:49:17
【问题描述】:

我正在尝试创建一个自定义上下文菜单,当用户右键单击我页面的某个部分时激活该菜单(我希望页面其余部分上的浏览器默认上下文菜单)。

我从父元素调用子元素:

<ContextMenu clickDomain={this.parentRef}>

(当然,在构造函数中我创建了参考:this.parentRef = React.createRef();)。

在子 &lt;ContextMenu&gt; 组件中,我尝试使用传递的 ref 为 contextmenu 事件设置域:

componentDidMount() {
        const self = this;
        console.log(this.props);
        console.log(!!self.props.clickDomain);
        console.log(!!self.props.clickDomain.current);
        const domain = self.props.clickDomain && self.props.clickDomain.current 
            ? self.props.clickDomain.current : document;
        console.log(domain);
        domain.addEventListener('contextmenu', 
             this.openContextMenu(self));
    }

(除其他外,openContextMenu 设置状态 visible: true 以及 x 和 y 坐标。)

但!!self.props.clickDomain.current 为假(self.props.clickDomain.current 为空),domain 为document。

所以即使父 ref 不在 DOM 中,子组件已经“挂载”了?

如何将对父组件的实时引用传递给子组件,以便我可以在子组件中在父组件上设置事件侦听器?

【问题讨论】:

  • 嘿,如果你要投票给我,请至少在评论中说明原因!
  • 你有理由使用domain.addEventListener('contextmenu')吗?看起来您可以简单地监视父组件上的onClick,设置一个状态,例如将isContext 状态设置为true,然后将其传递给&lt;ContextMenu isOpen={this.state.isOpen} /&gt;。在ContextMenu.render 内,如果this.props.isOpen === true,那么你可以简单地render 你的元素。
  • @SungM.Kim,感谢您的支持和回复!您的建议肯定会更直接,但在我看来,组件的可见性是该组件状态的一部分,而不是真正的父状态。我正在尝试使我的上下文菜单组件自包含,因此我可以轻松地重用它,而无需对主机/父级进行大量更改。

标签: javascript reactjs event-handling addeventlistener


【解决方案1】:

Callback refs 可能是一个解决方案。设置后,您可以使用状态来存储 ref,并将 this.state.ref 传递给 &lt;ContextMenu/&gt; 组件。

但我建议你试试这个:

class WithContextMenu extends React.Component {
    constructor(props) {
        super(props);
        this.state = {open: false};
    }

    openContextMenu(e) {
        e.preventDefault();
        this.setState({open: true});
    }

    render() {
        return (<React.Fragment>
            {React.cloneElement(
                React.Children.only(this.props.children),
                { onContextMenu: this.openContextMenu.bind(this) }
            )}
            { this.state.open && <div>context menu</div> }
        </React.Fragment>)
    }
}

// In any other component
const MyComponent = () => (
    <WithContextMenu>
      <div>
        <h1>Hello</h1>
        <p>Right-click to open context menu</p>
      </div>
    </WithContextMenu>
);

然后您可以使用上下文菜单装饰任何组件。以下是它的工作原理:

  1. 将任何组件包装在WithContextMenu 组件中
  2. onContextMenu 事件处理程序附加到包装的组件
  3. 触发事件处理程序时,上下文菜单本身会与包装的组件一起呈现

【讨论】:

  • 嗨皮埃尔,非常感谢您的回复!我试图了解您建议的代码在做什么以及它如何解决我的问题。看起来您是在 ContextMenu 的子代上设置事件处理程序,而不是在父代上设置(我想要的)?我看错了吗?
  • 不客气!我建议的是装饰器模式的实现。我更新了示例代码,使其更加明确。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 1970-01-01
  • 1970-01-01
  • 2014-08-14
相关资源
最近更新 更多