反应钩子。为什么不设置功能改变状态?
React hooks. Why doesn't set function change state?
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}`);
总是打印 false,而 setIsHidden(true)
总是被触发但似乎永远不会改变状态。为什么?基本上 isHidden 永远不会设置为 false,除非在 useState 初始化之后。
基本上发生的事情是你的 useEffect
在挂载和卸载时只运行两次(这显然是故意的),但是这样做的副作用是您在 onScroll
方法中检查的 isHidden
的值在其初始值(即 false
)处关闭 - 永远(直到卸载是).
您可以使用 setter 的函数形式,它接收状态的实际值并将所有分支逻辑放入其中。类似于:
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 {
// ...
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}`);
总是打印 false,而 setIsHidden(true)
总是被触发但似乎永远不会改变状态。为什么?基本上 isHidden 永远不会设置为 false,除非在 useState 初始化之后。
基本上发生的事情是你的 useEffect
在挂载和卸载时只运行两次(这显然是故意的),但是这样做的副作用是您在 onScroll
方法中检查的 isHidden
的值在其初始值(即 false
)处关闭 - 永远(直到卸载是).
您可以使用 setter 的函数形式,它接收状态的实际值并将所有分支逻辑放入其中。类似于:
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 {
// ...