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

Reactjs - Higher Order Component unmount not working correctly

我创建了一个 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" 继续监听事件,所以我收到错误消息 "Uncaught Error: findDOMNode was called on an unmounted component."

知道是什么原因造成的吗?

您的 removeEventListener 不工作的原因是因为您正试图删除 创建的函数。这同样适用于 addEventListener。这是两个完全不同的函数,彼此之间没有任何参考。

你必须绑定你的方法 _handleClickOutside 所以 React 知道它只有一个版本。你通过在构造函数中绑定它来做到这一点

constructor() {
    super();
    this._handleClickOutside.bind(this);
}

或使用 ES6 箭头方法自动绑定它

 _handleClickOutside = (e) => { ... }

现在你将绑定方法传递给你的事件监听器

 document.addEventListener('click', this._handleClickOutside, true);

并分别移除侦听器。

将此添加到构造函数中:

this._handleClickOutside = this._handleClickOutside.bind(this)

然后这样做:

componentDidMount() {
            document.addEventListener('click', this._handleClickOutside, true);
        }

        componentWillUnmount() {
            document.removeEventListener('click', this._handleClickOutside, true);
        }