React钩子,如何实现UseHideonscroll钩


const shouldHide = useHideOnScroll();
return shouldHide ? null : <div>something</div>

usehideonscroll行为应不在每个滚动上返回更新的值,而仅在发生更改时。

伪逻辑是以下内容:

if (scrolledDown && !isHidden) {
        setIsHidden(true);
      } else if (scrolledUp && isHidden) {
        setIsHidden(false);
      }

用文字,如果向下滚动而不是隐藏,则隐藏。如果向上滚动并隐藏了,则请不通过。但是,如果向下滚动并隐藏隐藏,什么都不做或滚动而不是隐藏,什么也不做。

您如何用钩子实现它?

在这里:

const useHideOnScroll = () => {
  const prevScrollY = React.useRef<number>();
  const [isHidden, setIsHidden] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => {
      setIsHidden(isHidden => {
        const scrolledDown = window.scrollY > prevScrollY.current!;
        if (scrolledDown && !isHidden) {
          return true;
        } else if (!scrolledDown && isHidden) {
          return false;
        } else {
          prevScrollY.current = window.scrollY;
          return isHidden;
        }
      });
    };
    console.log("adding listener");
    window.addEventListener("scroll", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
    };
  }, []);
  return isHidden;
};
const Navbar = () => {
  const isHidden = useHideOnScroll();
  console.info("rerender");
  return isHidden ? null : <div className="navbar">navbar</div>;
};
export default Navbar;

您可能会担心setIsHidden在每个onScroll上引起rerender,始终返回一些新的状态值,但是useState中的设置器足够聪明,只有在值实际更改时才更新。

您的 .navbar我添加了一个类)在出现时不应更改布局,否则您的片段将被锁定在无限循环中。这里也适合它:

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 30px;
  background: rgba(255, 255, 255, 0.8);
}

完整的代码框:https://codesandbox.io/s/13kr4xqrwq

使用React(16.8.0 )中的钩子


import React, { useState, useEffect } from 'react'
function getWindowDistance() {
    const { pageYOffset: vertical, pageXOffset: horizontal } = window
    return {
        vertical,
        horizontal,
    }
}
export default function useWindowDistance() {
    const [windowDistance, setWindowDistance] = useState(getWindowDistance())
    useEffect(() => {
        function handleScroll() {
            setWindowDistance(getWindowDistance())
        }
        window.addEventListener('scroll', handleScroll)
        return () => window.removeEventListener('scroll', handleScroll)
    }, [])
    return windowDistance
}

您需要使用window.addeventlistener和https://reactjs.org/docs/hooks-custom.html指南。

那是我的工作示例:

import React, { useState, useEffect } from "react";
const useHideOnScrolled = () => {
  const [hidden, setHidden] = useState(false);
  const handleScroll = () => {
    const top = window.pageYOffset || document.documentElement.scrollTop;
    setHidden(top !== 0);
  };
  useEffect(() => {
    window.addEventListener("scroll", handleScroll);
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);
  return hidden;
};
export default useHideOnScrolled;

实时演示:https://codesandbox.io/s/w0p3xkoq2l?fontsize=14

我认为名称 useIsScrolled()或类似的东西会更好

悬挂数小时后,这是我想到的。

const useHideOnScroll = () => {
  const [isHidden, setIsHidden] = useState(false);
  const prevScrollY = useRef<number>();
  useEffect(() => {
    const onScroll = () => {
      const scrolledDown = window.scrollY > prevScrollY.current!;
      const scrolledUp = !scrolledDown;
      if (scrolledDown && !isHidden) {
        setIsHidden(true);
      } else if (scrolledUp && isHidden) {
        setIsHidden(false);
      }
      prevScrollY.current = window.scrollY;
    };
    window.addEventListener("scroll", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
    };
  }, [isHidden]);
  return isHidden;
};

用法:

const shouldHide = useHideOnScroll();
return shouldHide ? null : <div>something</div>

它仍然是次优的,因为当isHidden更改时,我们重新分配了onScroll。其他一切都感觉太粗糙和无证件。我真的有兴趣找到一种做同样的方法,而无需重新分配onScroll。如果您知道一种方法:)

相关内容

  • 没有找到相关文章

最新更新