多个setState /状态冲突

时间:2019-06-13 18:30:24

标签: javascript reactjs

我有多个冲突状态,导致导航项目显示并在滚动后消失。在尝试检查较小的设备之前,滚动事件一直运行良好。似乎checkWidth中定义的状态导致显示导航项。

在这种情况下是否有更好的方法来处理多个状态?因此,它们仅在应有的状态下触发。任何帮助表示赞赏。

constructor(props) {
  super(props);

  this.state = {
    isTop: true,
  };
}
onScroll(isTop) {
  this.setState({ isTop });
}
componentDidMount() {
  this.updateWindowDimensions();
  window.addEventListener('resize', this.updateWindowDimensions);
  document.addEventListener('scroll', () => {
    const isTop = window.scrollY < window.innerHeight - 50;
    if (isTop !== this.state.isTop) {
      this.onScroll(isTop);
    }
  });

  this.checkWidth = () => {
    const match = window.matchMedia(`(max-width: 768px)`);
    if (match) {
      this.setState({isTop: false});
    }
  };

  this.checkWidth();
  window.addEventListener('resize', this.checkWidth);
}

2 个答案:

答案 0 :(得分:0)

  1. 您可以使用debounce

    例如,使用此工具,如果您在0.3s内多次调用滚动事件中侦听的函数,则在停止滚动后仅执行一次:

    var efficientScroll = debounce(function() {...}, 250);

  2. 为什么使用两个不同的函数监听resize事件。必要吗?也许您也可以改善它。并同时应用防抖功能。

答案 1 :(得分:0)

在移动设备上,方法checkWidth()会将isTop设置为false,即使在顶部。这可能会造成混淆。

我认为基于isTopisNarrowWidth这两个状态属性来控制导航菜单的可见性更为有意义。

或:您可以将isTop更改为navMenuVisible,并根据window.scrollYwindow.matchMedia()的值来计算此状态属性。这基本上将checkWidth()和您的onScroll回调合并到一个方法中。


(而且我会将所有这些逻辑从document.addEventListener回调移动到onScroll()。这不是必需的,但是将所有发生的事情放在此方法的内部滚动是有意义的。)