我创建了一个HOC来监听其包装组件之外的点击,以便包装的组件可以根据需要进行监听和反应。
HOC看起来像这样:
const addOutsideClickListener = (WrappedComponent) => {
class wrapperComponent extends React.Component {
componentDidMount() {
console.log('*** component did MOUNT called ***');
document.addEventListener('click', this._handleClickOutside.bind(this), true);
}
componentWillUnmount() {
console.log('*** component will UNMOUNT called ***');
document.removeEventListener('click', this._handleClickOutside.bind(this), true);
}
_handleClickOutside(e) {
const domNode = ReactDOM.findDOMNode(this);
if ((!domNode || !domNode.contains(e.target))) {
this.wrapped.handleClickOutside();
}
}
render() {
return (
<WrappedComponent
ref={(wrapped) => { this.wrapped = wrapped }}
{...this.props}
/>
);
}
}
return wrapperComponent;
}
它工作正常......大部分时间。
当卸载包装组件时,调用方法“componentWillUnmount”,但“removeEventListener”继续侦听事件,因此我收到错误消息 “未捕获的错误:在未安装的组件上调用了findDOMNode。”
任何可能导致此问题的想法?
答案 0 :(得分:3)
removeEventListener
无效的原因是您尝试删除新创建的函数。这同样适用于addEventListener
。这是两个完全不同的功能,没有任何参考。
你必须绑定你的方法_handleClickOutside
,以便React知道它的一个版本。您可以通过使用
constructor() {
super();
this._handleClickOutside.bind(this);
}
或使用ES6箭头方法
自动绑定它 _handleClickOutside = (e) => { ... }
现在使用
将绑定方法传递给eventlisteners document.addEventListener('click', this._handleClickOutside, true);
和remove listener。
答案 1 :(得分:1)
将其添加到构造函数:
this._handleClickOutside = this._handleClickOutside.bind(this)
然后执行此操作:
componentDidMount() {
document.addEventListener('click', this._handleClickOutside, true);
}
componentWillUnmount() {
document.removeEventListener('click', this._handleClickOutside, true);
}