调整大小时,我有一个事件,窗口将显示桌面侧边栏或移动侧边栏。如果window小于,但是如果我在桌面窗口中,有些变量不会立即更新以显示侧边栏,我可以使用class
我已经创建了一个沙箱https://codesandbox.io/s/sidebar-hooks-8oefi 要查看代码,我在App_class.js中具有类组件,如果在App中替换它,它可以工作,但是带有钩子(App.hoos.js文件,默认情况下在App.js中),我无法使其工作
感谢您的关注。我期待着您的答复。
在课堂上,我可以使用:
if (isMobile !== wasMobile) {
this.setState({
isOpen: !isMobile
});
}
const App = props => {
//minicomponent to update width
const useListenResize = () => {
const [isOpen, setOpen] = useState(false);
const [isMobile, setMobile] = useState(true);
//const [previousWidth, setPreviousWidth] = useState( -1 );
let previousWidth = -1;
const updateWidth = () => {
const width = window.innerWidth;
const widthLimit = 576;
let newValueMobile = width <= widthLimit;
setMobile(isMobile => newValueMobile);
const wasMobile = previousWidth <= widthLimit;
if (isMobile !== wasMobile) {
setOpen(isOpen => !isMobile);
}
//setPreviousWidth( width );
previousWidth = width;
};
useEffect(() => {
updateWidth();
window.addEventListener("resize", updateWidth);
return () => {
window.removeEventListener("resize", updateWidth);
};
// eslint-disable-next-line
}, []);
return isOpen;
};
const [isOpen, setOpen] = useState(useListenResize());
const toggle = () => {
setOpen(!isOpen);
};
return (
<div className="App wrapper">
<SideBar toggle={toggle} isOpen={isOpen} />
<Container fluid className={classNames("content", { "is-open": isOpen })}>
<Dashboard toggle={toggle} isOpen={isOpen} />
</Container>
</div>
);
};
export default App;
使用setState无效
答案 0 :(得分:2)
问题是在此处设置isMobile
值后
setMobile(isMobile => newValueMobile);
您将立即引用该值,
if (isMobile !== wasMobile) {
setOpen(isOpen => !isMobile);
}
由于async
的{{1}}性质,您一直在这里得到setState
的先前值。
要执行此操作,您需要对代码进行一些更改。
您正在直接更改isMobile
的值,您应该使previousWidth
处于一种状态,并使用setter函数更改该值。
previousWidth
在const [previousWidth, setPreviousWidth] = useState(-1);
setPreviousWidth(width); //setter function
之后,您无法立即获得价值。您应该使用另一个setState
和useEffect
作为依赖项数组的isMobile
。
previousWidth
答案 1 :(得分:0)
由于updateWidth
使用useEffect在组件安装中注册一次,因此它将引用陈旧状态(isMobile
),该状态始终为真,因此{{ 1}}将永远无法使用。
编辑:以下code说明了您问题的更简单版本:
setOpen(isOpen => !isMobile)
如果运行此代码,您会注意到,即使通过单击按钮更改const Counter = () => {
const [count, setCount] = useState(0)
const logCount = () => {
console.log(count);
}
useEffect(() => {
window.addEventListener('resize', logCount);
}, [])
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
)
}
的值,在调整浏览器大小时也始终会获得初始值(请检查控制台),这就是因为count
指的是在定义之时获得的状态。
@ ravibagul91答案有效,因为它从logCount
而不是从事件处理程序访问状态。
您可能想要检查:React hooks behaviour with event listener和Why am I seeing stale props or state inside my function?,它将使您对发生的事情有更好的了解。