使用React Hook进行滚动更新

时间:2019-08-11 19:53:33

标签: javascript reactjs react-hooks

我试图根据个人是否向下滚动组件来控制React组件的可见性。可见性作为“ in”属性传递到Fade元素中。

我已经使用UseEffect Hook设置了一个侦听器,该钩子将侦听器添加到onMount。实际的onScroll函数应该先更新scrollTop状态(即到页面顶部的高度的当前值),然后再更新滚动状态(将事件的滚动到页面顶部的状态与先前的状态进行比较,并且如果第一个大于第二个,则返回true)。

但是,由于某种原因,setScrollTop挂钩不起作用,并且滚动状态继续保持为0。

我在做什么错?这是完整的组件:

export const Header = (props) => {

  const classes = useStyles();

  const [scrolling, setScrolling] = useState(false);
  const [scrollTop, setScrollTop] = useState(0);

  const onScroll = (e) => {
    setScrollTop(e.target.documentElement.scrollTop);
    setScrolling(e.target.documentElement.scrollTop > scrollTop);
  }

  useEffect(() => {
    window.addEventListener('scroll', onScroll);
  },[]);

  useEffect(() => {
    console.log(scrollTop);
  }, [scrollTop])

  return (
   <Fade in={!scrolling}>
      <AppBar className={classes.header} position="fixed">

  ....

2 个答案:

答案 0 :(得分:4)

您缺少钩子中的依赖项。试试这个:

  useEffect(() => {
    const onScroll = e => {
      setScrollTop(e.target.documentElement.scrollTop);
      setScrolling(e.target.documentElement.scrollTop > scrollTop);
    };
    window.addEventListener("scroll", onScroll);

    return () => window.removeEventListener("scroll", onScroll);
  }, [scrollTop]);

通过在onScroll内移动useEffect,您不需要在挂钩的依赖项上进行跟踪,但是由于它使用了组件范围内的scrollTop,因此您需要添加它。

或者,如果由于某种原因您不想在onScroll中移动useEffect定义,则需要将onScroll包装在useCallback中并进行跟踪在useEffect的依赖项数组中。

通常,我建议将react-hooks/exhaustive-deps添加到您的ESlint规则中

此外,最好在清理功能中删除事件监听器。

答案 1 :(得分:1)

或者您可以使用window.pageYOffset。这样对我来说更容易理解:

const [scrolling, setScrolling] = useState(false);
  const [scrollTop, setScrollTop] = useState(0);

  useEffect(() => {
    function onScroll() {
      let currentPosition = window.pageYOffset; // or use document.documentElement.scrollTop;
      if (currentPosition > scrollTop) {
        // downscroll code
        setScrolling(false);
      } else {
        // upscroll code
        setScrolling(true);
      }
      setScrollTop(currentPosition <= 0 ? 0 : currentPosition);
    }

    window.addEventListener("scroll", onScroll);
    return window.addEventListener("scroll", onScroll);
  }, [scrollTop]);