新的React钩子和状态,试图找出为什么我的代码不工作。
我有一个App.js
文件和一个名为Menu.js
的子组件。本质上,Menu.js
包含一个菜单,我想显示一个名为isOpen
的变量是否为true
,并隐藏isOpen
是否为false
。我已经在App.js
的父级添加了该功能,因为我有另一个组件需要能够更新isOpen
的状态,但该组件与我的问题无关。以下是相关代码:
App.js:
import Menu from "./components/Menu";
import { useState } from "react";
export default function App() {
const [isOpen, setIsOpen] = useState(false);
const toggleState = () => setIsOpen(!isOpen);
console.log(isOpen);
// This will console log either true or false
const menuBtn = document.querySelector(".hamburgermenu");
const mobileMenu = document.querySelector(".mobilemenu");
// These are elements on the child component, Menu.js
if (isOpen) {
menuBtn.classList.add("open");
mobileMenu.style.zIndex = "5";
// This should reveal the menu if the value of isOpen is true
} else {
menuBtn.classList.remove("open");
mobileMenu.style.zIndex = "0";
// This should hide the menu if the value of isOpen is false
}
return (
<div>
<Menu togglestate={toggleState} />
// Passing togglestate down to Menu.js as a prop
</div>
);
}
Menu.js:
export default function Menu(props) {
return (
<div>
<div className="hamburgermenu" onClick={props.togglestate}>Stuff in here</div>
// Clicking this div will toggle the value of isOpen between true and false
<div className="mobilemenu">Stuff in here</div>
</div>
);
}
当我试图运行,我的整个应用程序中断,我得到错误TypeError: Cannot read properties of null (reading 'classList')
在menuBtn.classList.remove("open");
我知道我的问题在于默认状态是false
,因此它将首先尝试运行else
语句。但是,因为类open
还没有添加到menuBtn
元素中,所以没有open
类可以删除,所以它出错了。
我试图在原来的else
语句中添加另一个嵌套的if/else
语句,基本上是说如果元素有一个叫做open
的类,删除它,像这样:
if (isOpen) {
menuBtn.classList.add("open");
mobileMenu.style.zIndex = "5";
} else {
if (menuBtn.classList.contains("open")) {
menuBtn.classList.remove("open");
mobileMenu.style.zIndex = "0";
} else {
mobileMenu.style.zIndex = "0";
}
}
我也试过完全远离类,只是直接改变样式作为测试,像这样:
if (menuOpen) {
menuBtn.style.display = "block";
mobileMenu.style.zIndex = "5";
} else {
menuBtn.style.display = "none";
mobileMenu.style.zIndex = "0";
}
但是我仍然在同一行出现错误,TypeError: Cannot read properties of null (reading 'style')
在menuBtn.style.display = "block";
我知道这有点乱。我相信有更好的方法来做这件事,但这就是我用我现有的知识来做这件事的方法。如果有更简单的方法,我愿意接受建议!
React的总体思路是不需要直接处理像document.querySelector(".hamburgermenu")
这样的DOM
不新建函数toggleState
,直接将设置函数setIsOpen
传递给菜单函数,如下所示(连同当前打开状态)
<Menu isOpen={isOpen} togglestate={setIsOpen} />
那么整个if-else条件可以简化为如下的三元操作符:
export default function Menu({ isOpen, togglestate }) {
return (
<>
<div
className={'hamburgermenu' + isOpen ? ' open' : ''}
onClick={() => togglestate(!isOpen)}
>
// Clicking this div will toggle the value of isOpen between true and
false
</div>
<div className="mobilemenu" style={{ zIndex: isOpen ? 5 : 1 }}>
Stuff in here
</div>
</>
);
}