Reactjs - 高阶组件卸载无法正常工作

时间:2017-01-19 09:59:43

标签: reactjs react-jsx

我创建了一个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。”

任何可能导致此问题的想法?

2 个答案:

答案 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);
        }