反应:在后代上定义ref prop?

时间:2019-06-18 10:04:59

标签: reactjs

我想创建一个包装器组件来处理组件的外部点击。

我想避免两件事,这可能是不可能的。

  • 避免创建几乎多余的<div />来处理ref组件中的<OutsideClick />

  • 避免每次要包装组件时都必须处理this.props.passedInRef

到目前为止,我可以得到的最干净的实现是使用HOC,如下所示。您会看到我也尝试使用React.cloneElement(),但如果已注释掉,我就离开了。

const onOutsideClick = (Component) => {
  class OnOutsideClick extends React.PureComponent {

    capturedEvents = ['touchend', 'click'];

    componentDidMount() {
      this.capturedEvents.forEach((event) => {
        document.addEventListener(event, this.handleOutsideClick, true);
      });
    }

    componentWillUnmount() {
      this.capturedEvents.forEach((event) => {
        document.removeEventListener(event, this.handleOutsideClick, true);
      });
    }

    handleOutsideClick = (e) => {
      if (!this.wrapperRef.contains(e.target)) {
        console.log('handled Outside Click');
      }
    }

    setWrapperRef = (node) => {
      this.wrapperRef = node;
    }

    // render() {
    //   return React.cloneElement(this.props.children, {
    //     ref: this.setWrapperRef,
    //   });
    // }

    render() {
      return <Component ref={this.setWrapperRef} {...this.props} />;
    }
  }
  return OnOutsideClick;
};

点击时出现以下错误:_this.wrapperRef.contains is not a function at HTMLDocument.OnOutsideClick._this.handleOutsideClick

如果将render方法更改为:

render() {
      return <Component forwardRef={this.setWrapperRef} {...this.props} />;
    }

在后代组件渲染方法中,我必须定义:

<div ref={this.props.forwardRef}>
    ...
</div>

这感觉就像我在弄脏后代。是否可以仅将ref作为后代传递给后代?

1 个答案:

答案 0 :(得分:1)

有多种处理方法。

首先:如您所建议,您可以将ref作为具有不同名称的道具传递,然后将其附加到div元素上

第二步::您可以使用forwardRef api将引用转发到看起来像这样的组件

const MyComponent = React.forwardRef((props, ref) => (
    <div ref={ref}>{/* content here */}</div>
));

第三:您可以避免使用React.findDOMNode来转发转发。但是,这不是推荐的方法,您必须尽可能转发参考

handleOutsideClick = (e) => {
  if (!ReactDOM.findDOMNode(this.wrapperRef).contains(e.target)) {
    console.log('handled Outside Click');
  }
}