当我点击菜单项时,页面加载但菜单保持打开状态。
这是移动菜单,如果JSX:
const MobileMenu = () => {
const navigation = [
{ link: '/applications', text: 'Applications' },
{ link: '/multi-media', text: 'Media' },
{ link: '/websites', text: 'Websites' },
{ link: '/mobile-apps', text: 'Mobile' },
{ link: '/support', text: 'Support' },
{ link: '/contact', text: 'Contact' },
{ link: '/', text: 'Login' },
];
return (
<NavMenuContainer>
<NavList>
<div className="flex pb-4 lg:px-6 lg:hidden">
<Searchbar id="mobile-search" />
</div>
{navigation.map(nav => (
<NavLink key={nav.text}>
<Link href={nav.link}><a>
{nav.text}
</a></Link>
</NavLink>
))}
</NavList>
</NavMenuContainer>
);
};
export default MobileMenu
这是NAV MobileMenu菜单在(JSX:
)export default function HamburgerMenu(props) {
const [isOpen, setOpen] = useState(false);
//change
const toggleMenu = () => {
let dd = document.body;
dd.classList.toggle("navbar-mobile");
setOpen(!isOpen);
};
return (
<Theburger>
<HamburgerMenuContainer>
<MenuToggle toggle={toggleMenu} isOpen={isOpen} />
<MenuContainer
initial={false}
animate={isOpen ? "open" : "closed"}
variants={menuVariants}
transition={menuTransition}
>
<ContentContainer>
<MobileMenu isOpen={isOpen} />
</ContentContainer>
</MenuContainer>
</HamburgerMenuContainer>
</Theburger>
);
}
这是网站的主菜单,它是TSX:
const Navbar: FC<NavbarProps> = ({ links }) => (
<NavbarRoot>
<Container>
<div className={s.nav}>
<div className="flex items-center">
<Link href="/"><a>
<div className="logo">
<Image width={106} height={27} src="/logo.svg" alt="brand" />
</div>
</a></Link>
<nav className={s.navMenu}>
{[...links3 ].map((page) => (
<span key={page.url}>
<Link href={page.url!}>
<a className={s.link}>
{page.name}
</a>
</Link>
</span>
))}
{links?.map((l) => (
<Link href={l.href} key={l.href}>
<a className={s.link}>{l.label}</a>
</Link>
))}
</nav>
</div>
<div className="flex items-center justify-end flex-1 space-x-8 mr-5">
<UserNav />
</div>
<div className="flex items-center justify-end flex-2">
<Nav />
</div>
</div>
</Container>
</NavbarRoot>
)
export default Navbar
这是一个nextjs应用程序,我在_app中使用布局组件。我不确定这是否重要,但它真的不应该,我错过了tsx与jsx,根据NextJS和javascript的文档,混合它们通常不会引起问题。
您缺少将状态作为道具提供给toggle菜单函数。因此,isOpen总是为false,状态总是被更改为true。
把你的toggleMenu()改成toggleMenu(isOpen)就可以了
export default function HamburgerMenu(props) {
const [isOpen, setOpen] = useState(false);
//change
const toggleMenu = (myState) => {
let dd = document.body;
dd.classList.toggle("navbar-mobile");
setOpen(!isOpen);
};
return (
<Theburger>
<HamburgerMenuContainer>
<MenuToggle toggle={()=>toggleMenu(isOpen)} isOpen={isOpen} />
<MenuContainer
initial={false}
animate={isOpen ? "open" : "closed"}
variants={menuVariants}
transition={menuTransition}
>
<ContentContainer>
<MobileMenu isOpen={isOpen} />
</ContentContainer>
</MenuContainer>
</HamburgerMenuContainer>
</Theburger>
);
}
你遇到的菜单总是可见的原因是,当react编译函数时,不管它是否被修改,都会使用初始值。导致下面的函数总是console log "initial"即使状态已经改变。
function A() {
const [textState, setTextState] = useState('initial');
const printState = () => {
console.log(textState);
setTextState('changed');
}
return <button onClick={()=>printState()}>Print me</button>
}
在以下两种情况下的行为是不同的,要么是来自父级的状态,要么是给函数的道具。
父道具
function B({textState, setTextState}) {
const printState = () => {
console.log(textState);
setTextState('changed');
}
return <button onClick={()=>printState()}>Print me</button>
}
在函数B中,printState函数作为一个道具给出,当道具改变时,该函数被重新渲染,这也导致printState函数被重新编译,新的道具导致控制台日志改变,而不是初始化。
另一种选择是在组件本身中处理状态,并将状态作为prop提供给我们的函数。
function C() {
const [textState, setTextState] = useState('initial');
const printState = (prop) => {
console.log(prop);
setTextState('changed');
}
return <button onClick={()=>printState(textState)}>Print me</button>
}
在这里,prop被直接赋给printState函数,而printState函数没有被重新编译,更新后的状态被作为prop赋给并相应地处理