在卸载 React 时删除事件监听器

新手上路,请多包涵

我有这样的反应的高阶组件:

 export default function (InnerComponent) {
    class InfiniteScrolling extends React.Component {

        constructor(props){
            super(props);
        }

        componentDidMount() {
            window.addEventListener('scroll', this.onScroll.bind(this), false);
        }

        componentWillUnmount() {
            window.removeEventListener('scroll', this.onScroll.bind(this), false);
        }

        onScroll() {
            if ((window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 50)) {
                const { scrollFunc } = this.props;
                scrollFunc();
            }
        }

        render() {
            return <InnerComponent {...this.props} />;
        }
    }

    InfiniteScrolling.propTypes = {
        scrollFunc: PropTypes.func.isRequired
    };

    return InfiniteScrolling;
}

卸载通过 InfiniteScrolling 包装的组件后,它们仍然抛出错误(当我滚动时):

警告:setState(…):只能更新已安装或安装的组件。这通常意味着您在未安装的组件上调用了 setState() 。这是一个空操作。请检查未定义组件的代码。

即使我确实删除了组件卸载上的 scroll 事件。它没有用。

但是当我将代码更改为这样时:

 constructor(props){
    super(props);
    this.onScroll = this.onScroll.bind(this);
}

componentDidMount() {
    window.addEventListener('scroll', this.onScroll, false);
}

componentWillUnmount() {
    window.removeEventListener('scroll', this.onScroll, false);
}

一切似乎都运行良好,没有任何问题。

我觉得它们是完全一样的东西,但是第二个工作正常,而第一个在控制台中抛出错误,如前所述!

原文由 Ant‘s 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 573
2 个回答

.bind 总是创建一个新函数,所以你需要像下面那样做,所以它添加和删除了相同的函数。

     constructor(props){
        super(props);
        this.onScroll = this.onScroll.bind(this); //bind function once
    }

    componentDidMount() {
        window.addEventListener('scroll', this.onScroll, false);
    }

    componentWillUnmount() {
        // you need to unbind the same listener that was binded.
        window.removeEventListener('scroll', this.onScroll, false);
    }

原文由 Yury Tarabanko 发布,翻译遵循 CC BY-SA 4.0 许可协议

      componentDidMount() {
            window.addEventListener('scroll', this.onScroll, false);
        }

        componentWillUnmount() {
            window.removeEventListener('scroll', this.onScroll, false);
        }
        // use arrow function instead
        onScroll = () => {
            if ((window.innerHeight + window.scrollY) >= (document.body.offsetHeight - 50)) {
                const { scrollFunc } = this.props;
                scrollFunc();
            }
        }

或者您可以使用 Arrow functions 来解决 .bind(this) 问题,它工作得很好。

原文由 The pyramid 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题