首页 > 解决方案 > 使用窗口事件侦听器时反应更新警告

问题描述

当我离开路由组件时,我收到以下警告:

警告:只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState、replaceState 或 forceUpdate。这是一个无操作。

添加滚动事件侦听器后,警告开始出现。如何防止出现此警告?我只绑定了一次事件方法。事件监听器在 componentDidMount 中添加,在 componentWillUnmount 中移除。

class DashboardRoute extends React.Component {
    constructor (props) {
        super(props)
        this.handleScroll = this.handleScroll.bind(this);
        this.state = {
            scrolled: false
        };
    }

    componentDidMount () {
        window.addEventListener('scroll', throttle(this.handleScroll, 250));
    }

    componentWillUnmount () {
        window.removeEventListener('scroll', throttle(this.handleScroll, 250));
    }

    handleScroll (e) {
        let scrolled = (window.scrollY > 0);
        if (scrolled !== this.state.scrolled) {
            this.setState({scrolled: scrolled});
        }
    }

    render () {
        return (
            <div>
                <!-- Component code -->
            </div>
        );
    }
}

标签: javascriptreactjs

解决方案


由于滚动事件处理程序可能会延迟多达 250 毫秒,因此您的组件可能会在它被调用之前被卸载。这取决于在DashboardRoute整个应用程序中的使用方式。

您可以使用一个名为 eg 的实例变量_mounted来跟踪组件是否实际上仍然挂载,并在使用之前在滚动处理程序中使用它setState

window.removeEventListener('scroll', throttle(this.handleScroll, 250))也会尝试移除一个新创建的函数作为滚动监听器,所以创建的监听器window.addEventListener('scroll', throttle(this.handleScroll, 250))不会被移除。您可以创建一次节流方法并引用它。

例子

class DashboardRoute extends React.Component {
  _mounted = true;
  state = {
    scrolled: false
  };

  componentDidMount() {
    window.addEventListener("scroll", this.handleScroll);
  }

  componentWillUnmount() {
    this._mounted = false;
    window.removeEventListener("scroll", this.handleScroll);
  }

  handleScroll = throttle(e => {
    let scrolled = window.scrollY > 0;
    if (this._mounted && scrolled !== this.state.scrolled) {
      this.setState({ scrolled: scrolled });
    }
  }, 250);

  render() {
    return <div>{/* ... */}</div>;
  }
}

推荐阅读