const shouldHide = useHideOnScroll();
return shouldHide ? null : <div>something</div>
useHideOnScroll行为不应在每次滚动时都返回更新的值,而应仅在发生更改时才返回。
伪逻辑如下:
if (scrolledDown && !isHidden) {
setIsHidden(true);
} else if (scrolledUp && isHidden) {
setIsHidden(false);
}
换句话说,如果向下滚动而不是隐藏,则隐藏。如果向上滚动并隐藏,则取消隐藏。但是,如果向下滚动并隐藏,则不执行任何操作;或者向上滚动但不隐藏,则不执行任何操作。
如何用钩子实现呢?
答案 0 :(得分:2)
在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
}
答案 1 :(得分:1)
您需要使用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()
或类似的名称会更好
答案 2 :(得分:1)
这里:
[dsivaji@FADL155 ~]$ cat debug_record.txt
==============================================================================
20190307 10:48:34.845 - INFO - + START SUITE: S SUITE [ ]
==============================================================================
20190307 10:48:34.858 - INFO - +- START SUITE: S SUITE.Dinesh [ ]
==============================================================================
20190307 10:48:34.859 - INFO - +-- START TEST: DEMO [ ]
------------------------------------------------------------------------------
20190307 10:48:34.860 - INFO - +--- START KW: BuiltIn.Log [ "Testcase start" ]
20190307 10:48:34.860 - INFO - "Testcase start"
20190307 10:48:34.861 - INFO - +--- END KW: BuiltIn.Log (1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20190307 10:48:34.861 - INFO - +--- START KW: test.Sample [ ]
20190307 10:48:34.862 - INFO - THIS IS INSIDE SAMPLE
20190307 10:48:34.863 - INFO - +--- END KW: test.Sample (1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20190307 10:48:34.863 - INFO - +--- START KW: BuiltIn.Log [ "Testcase end" ]
20190307 10:48:34.864 - INFO - "Testcase end"
20190307 10:48:34.865 - INFO - +--- END KW: BuiltIn.Log (1)
------------------------------------------------------------------------------
20190307 10:48:34.866 - INFO - +-- END TEST: DEMO (7)
------------------------------------------------------------------------------
20190307 10:48:34.869 - INFO - +- END SUITE: S SUITE.Dinesh (22)
==============================================================================
20190307 10:48:34.871 - INFO - + END SUITE: S SUITE (141)
==============================================================================
您可能会担心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
中的setter很聪明,仅当值具有真的改变了。
此外,您的useState
(我已经向其中添加了一个类)不应在布局出现时更改布局,否则您的代码段将陷入无限循环中。这也是适合的样式:
.navbar
答案 3 :(得分:0)
经过几个小时的摇晃,这就是我的想法。
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>
它仍然不是最佳选择,因为我们在onScroll
更改时重新分配了isHidden
。其他所有内容都显得过于骇人听闻,没有记载。我真的很想找到一种方法来完成上述任务,而无需重新分配onScroll
。如果您知道方法,请发表评论:)