点击导航栏菜单图标触发状态更新时页面冻结崩溃求助
问题:点击导航栏菜单图标导致页面冻结崩溃
点击导航栏中切换菜单状态的图标时,页面会完全冻结并崩溃。但直接将useState初始值设为true或false时,菜单能正常显示。尝试过以下方案但均未解决:
- 使用
useEffect:页面刷新后菜单自动打开,但无法通过按钮控制状态 - 使用
useCallback:出现和直接使用useState相同的页面崩溃问题
原代码
import React, {useState} from 'react'; import {Menu} from '@mui/icons-material'; function Navbar() { const [menuClicked, setMenuClicked] = useState(false); const updateMenu = () => { setMenuClicked(!menuClicked) } return( <div className='h-16 z-20 relative'> <div className='fixed top-0 text-left text-6xl font-bold items-center bg-white/40 h-20 w-full flex dark:text-white dark:bg-neutral-900/40'> <div className='flex flex-1 items-center pb-5'> <span className='pl-4'>psue</span> </div> <div className='flex justify-end w-7/12 scale-0 md:scale-100 items-center'> <ul className='flex text-xl gap-12 pb-0'> <li className=''> <a href='/'>Home</a> </li> <li> <a href='/livechat'>Live Chat</a> </li> <li> {checkLogin ? (<a href='/profile'>{auth.currentUser.email.substring(0, auth.currentUser.email.indexOf('@'))}</a>) : (<a onClick={signOutFunction} href='/login'>Login</a>)} </li> </ul> </div> <div className='z-20 pr-5 pb-5 scale-150 overflow-x-hidden md:scale-0'> <Menu onClick={() => updateMenu()} className='cursor-pointer'/> </div> </div> <div className={menuClicked ? 'translate-x-0 transition fixed bottom-0 top-0 right-0 h-screen w-64 z-10' : 'transition translate-x-72 fixed top-0 right-0 h-screen w-0'}> <div className='bg-white/30 dark:bg-neutral-900/30 dark:text-white fixed right-0 top-0 w-full h-full'> <ul className='flex flex-col text-xl gap-16 h-full w-full justify-center items-center backdrop-blur-lg font-bold'> <li> <CloseIcon onClick={() => updateMenu()} className='cursor-pointer scale-150 fixed top-24'/> </li> <li className=''> <a href='/'>Home</a> </li> <li> <a href='/livechat'>Live Chat</a> </li> <li> {checkLogin ? (<a href='/profile'>{auth.currentUser.email.substring(0, auth.currentUser.email.indexOf('@'))}</a>) : (<a onClick={signOutFunction} href='/login'>Login</a>)} </li> </ul> </div> </div> </div> ) } export default Navbar;
问题原因分析
- 闭包导致状态更新异常:
updateMenu里用!menuClicked切换状态时,依赖的是函数创建时捕获的旧状态值。如果组件因其他原因重渲染,这个值可能不是最新的,反复触发错误的状态更新,导致页面冻结。 auth.currentUser空值未处理:当checkLogin为true,但auth.currentUser还未初始化完成时,直接访问auth.currentUser.email会抛出错误,直接导致组件崩溃。- 缺失
CloseIcon导入:代码里使用了CloseIcon但未从MUI图标库导入,属于运行时错误,会直接引发页面崩溃。
修复方案
1. 用函数式更新解决闭包问题
状态更新时不依赖闭包里的旧值,改用函数式更新确保拿到最新状态:
const updateMenu = () => { setMenuClicked(prev => !prev); }
2. 处理auth.currentUser空值情况
在访问邮箱前先判断auth.currentUser是否存在,避免抛出错误:
{checkLogin ? ( auth.currentUser ? ( <a href='/profile'>{auth.currentUser.email.substring(0, auth.currentUser.email.indexOf('@'))}</a> ) : ( <span>加载中...</span> ) ) : ( <a onClick={signOutFunction} href='/login'>Login</a> )}
3. 导入缺失的CloseIcon
从MUI图标库补全导入:
import {Menu, CloseIcon} from '@mui/icons-material';
4. 优化菜单容器样式(可选)
原菜单容器的w-0可能导致布局异常,调整样式让过渡更稳定:
<div className={menuClicked ? 'translate-x-0 transition-all duration-300 fixed bottom-0 top-0 right-0 h-screen w-64 z-10' : 'translate-x-full transition-all duration-300 fixed top-0 right-0 h-screen w-64 z-10 invisible'}>
修复后完整代码
import React, {useState} from 'react'; import {Menu, CloseIcon} from '@mui/icons-material'; function Navbar() { const [menuClicked, setMenuClicked] = useState(false); const updateMenu = () => { setMenuClicked(prev => !prev); } return ( <div className='h-16 z-20 relative'> <div className='fixed top-0 text-left text-6xl font-bold items-center bg-white/40 h-20 w-full flex dark:text-white dark:bg-neutral-900/40'> <div className='flex flex-1 items-center pb-5'> <span className='pl-4'>psue</span> </div> <div className='flex justify-end w-7/12 scale-0 md:scale-100 items-center'> <ul className='flex text-xl gap-12 pb-0'> <li className=''> <a href='/'>Home</a> </li> <li> <a href='/livechat'>Live Chat</a> </li> <li> {checkLogin ? ( auth.currentUser ? ( <a href='/profile'>{auth.currentUser.email.substring(0, auth.currentUser.email.indexOf('@'))}</a> ) : ( <span>加载中...</span> ) ) : ( <a onClick={signOutFunction} href='/login'>Login</a> )} </li> </ul> </div> <div className='z-20 pr-5 pb-5 scale-150 overflow-x-hidden md:scale-0'> <Menu onClick={updateMenu} className='cursor-pointer'/> </div> </div> <div className={menuClicked ? 'translate-x-0 transition-all duration-300 fixed bottom-0 top-0 right-0 h-screen w-64 z-10' : 'translate-x-full transition-all duration-300 fixed top-0 right-0 h-screen w-64 z-10 invisible'}> <div className='bg-white/30 dark:bg-neutral-900/30 dark:text-white fixed right-0 top-0 w-full h-full'> <ul className='flex flex-col text-xl gap-16 h-full w-full justify-center items-center backdrop-blur-lg font-bold'> <li> <CloseIcon onClick={updateMenu} className='cursor-pointer scale-150 fixed top-24'/> </li> <li className=''> <a href='/'>Home</a> </li> <li> <a href='/livechat'>Live Chat</a> </li> <li> {checkLogin ? ( auth.currentUser ? ( <a href='/profile'>{auth.currentUser.email.substring(0, auth.currentUser.email.indexOf('@'))}</a> ) : ( <span>加载中...</span> ) ) : ( <a onClick={signOutFunction} href='/login'>Login</a> )} </li> </ul> </div> </div> </div> ) } export default Navbar;
内容的提问来源于stack exchange,提问作者lewos psue
相关产品推荐
相关产品推荐

