我正在尝试创建一个网页,该网页的右上角有一个固定的汉堡包图标,单击时会打开一个导航栏。如果用户在导航栏之外单击,则导航栏应关闭并且汉堡包图标应再次出现。
我使用 nextjs,而 nextjs 不接受服务器端组件中的用户交互,因此我必须打开另一个名为 CrMenuWrapper 的文件。
'use client'
import logger from '@/utils/logger'
import { NextPage } from 'next'
import { useEffect, useRef, useState } from 'react'
interface Props { }
const CrMenuWrapper: NextPage<Props> = ({ }) => {
const [isMenuClicked, setIsMenuClicked] = useState(false)
const phoneMenu: React.RefObject<HTMLDivElement> = useRef(null)
const menuButton: React.RefObject<HTMLDivElement> = useRef(null)
logger(isMenuClicked)
function handleOnClick(e: any) {
if (phoneMenu.current && isMenuClicked && !phoneMenu.current.contains(e.target)) {
setIsMenuClicked(prevIsMenuClicked => !prevIsMenuClicked)
} else if (menuButton.current && !isMenuClicked && menuButton.current.contains(e.target)) {
logger("clicked")
setIsMenuClicked(prevIsMenuClicked => !prevIsMenuClicked)
}
}
useEffect(() => {
document.addEventListener('click', (e) => handleOnClick(e))
return () => {
document.removeEventListener('click', (e) => handleOnClick(e))
};
}, [])
return <div>
<div ref={phoneMenu} className={`fixed z-50 bg-gradient-to-bl from-violet-600/30 backdrop-blur-sm to-indigo-600/30 bg-no-repeat bg-top top-0 right-0 transition-all border-2 border-[var(--secondary-rgb)]
w-[75vw] aspect-square rounded-es-full md:hidden origin-top-right duration-300
${isMenuClicked ? " scale-100 rotate-0" : " scale-0 rotate-45"}`}>
</div>
<div ref={menuButton} className={` bg-transparent md:hidden fixed aspect-square h-12 top-10 backdrop-blur-md right-10 stroke-0 hover:cursor-pointer
border-[var(--secondary-rgb)] p-2.5 rounded-full border-2 hover:scale-125 transition-all opacity-70 hover:opacity-100
${isMenuClicked ? " scale-0" : " scale-100"}`}>
<svg id="nav-svg" stroke="currentColor" fill="currentColor" className={`fill-[var(--primary-rgb)]
`} viewBox="0 0 24 24" height="inherit" width="inherit" xmlns="http://www.w3.org/2000/svg"><path id="nav-path" d="M16 18V20H5V18H16ZM21 11V13H3V11H21ZM19 4V6H8V4H19Z"></path></svg>
</div>
</div>
}
export default CrMenuWrapper
CrMenuWrapper.tsx
问题是当单击按钮时,它将按钮缩放到 0 并打开导航栏;但是,当我尝试单击导航之外时,它不会关闭。此外,当我在handleOnClick 内部记录 isMenuClicked 时,它会记录 false;然而,当我把它放在上面时(如上所示),它记录为 true,然后不会自行更新。
我的 10 倍编码器可以帮我解决这个问题吗?
谢谢,
嗯,
我自己解决了这个问题,对于那些想知道的人:
您所要做的就是将
isMenuClicked
添加为 的输入
useEffect(() => {
document.addEventListener('click', (e) => handleOnClick(e))
return () => {
document.removeEventListener('click', (e) => handleOnClick(e))
};
}, [])
因此它应该看起来像这样:
const [isMenuClicked, setIsMenuClicked] = useState(false)
//extra code bla bla bla ...
useEffect(() => {
document.addEventListener('click', (e) => handleOnClick(e))
return () => {
document.removeEventListener('click', (e) => handleOnClick(e))
};
}, [isMenuClicked])
事件侦听器的工作方式可能是保持状态,除非您另有说明。
谢谢。