我想创建一个包装器组件来处理组件的外部点击。
我想避免两件事,这可能是不可能的。
避免创建几乎多余的<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作为后代传递给后代?
答案 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');
}
}