const Navbar = () => {
const prevScrollY = React.useRef<number>();
const [isHidden, setIsHidden] = React.useState(false);
React.useEffect(() => {
const onScroll = () => {
const scrolledDown = window.scrollY > prevScrollY.current!;
console.log(`is hidden ${isHidden}`);
if (scrolledDown && !isHidden) {
setIsHidden(true);
console.log(`set hidden true`);
} else if (!scrolledDown && isHidden) {
console.log(`set hidden false. THIS NEVER HAPPENS`);
setIsHidden(false);
}
prevScrollY.current = window.scrollY;
};
console.log("adding listener");
window.addEventListener("scroll", onScroll);
return () => {
window.removeEventListener("scroll", onScroll);
};
}, []);
return isHidden ? null : <div>navbar</div>;
};
完整示例
console.log(`is hidden ${isHidden}`);
总是打印错误,并且setIsHidden(true)
总是会触发,但似乎永远不会改变状态。为什么?基本上,除了在美国初始化之后,Ishidden永远不会是Setto False。
基本上发生的是您的useEffect
仅在坐骑和Unmount上运行两次(,这显然是故意的),但是不需要的副作用是您在onScroll
方法中检查的isHidden
值以其初始值(即false
) - Forever(直到删除为)。)。
您可以使用设置器的功能形式,其中它接收状态的实际值并将所有分支逻辑放在其中。类似:
setIsHidden(isHidden => { // <- this will be the proper one
const scrolledDown = window.scrollY > prevScrollY.current!;
console.log(`is hidden ${isHidden}`);
if (scrolledDown && !isHidden) {
console.log(`set hidden true`);
return true;
} else if (!scrolledDown && isHidden) {
console.log(`set hidden false. THIS NEVER HAPPENS`);
return false;
} else {
// ...