You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Vite+Material UI中ResponsiveAppBar报Unexpected token错误求助

React+Vite+Material UI中ResponsiveAppBar示例报错解决
  • 技术栈:React + Vite + Material UI
  • 问题:运行Material UI官网的ResponsiveAppBar示例时出现语法错误,同站点的ButtonAppBar示例可正常运行(后者未使用TypeScript类型注解)

我的ResponsiveAppBar代码(与官网示例一致)

import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import Menu from '@mui/material/Menu';
import MenuIcon from '@mui/icons-material/Menu';
import Container from '@mui/material/Container';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import MenuItem from '@mui/material/MenuItem';
import AdbIcon from '@mui/icons-material/Adb';

const pages = ['Products', 'Pricing', 'Blog'];
const settings = ['Profile', 'Account', 'Dashboard', 'Logout'];

function ResponsiveAppBar() {
  const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null);
  const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(null);

  const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
    setAnchorElNav(event.currentTarget);
  };
  const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
    setAnchorElUser(event.currentTarget);
  };

  const handleCloseNavMenu = () => {
    setAnchorElNav(null);
  };

  const handleCloseUserMenu = () => {
    setAnchorElUser(null);
  };

  return (
    <AppBar position="static">
      <Container maxWidth="xl">
        <Toolbar disableGutters>
          <AdbIcon sx={{ display: { xs: 'none', md: 'flex' }, mr: 1 }} />
          <Typography
            variant="h6"
            noWrap
            component="a"
            href="/"
            sx={{
              mr: 2,
              display: { xs: 'none', md: 'flex' },
              fontFamily: 'monospace',
              fontWeight: 700,
              letterSpacing: '.3rem',
              color: 'inherit',
              textDecoration: 'none',
            }}
          >
            LOGO
          </Typography>

          <Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
            <IconButton
              size="large"
              aria-label="account of current user"
              aria-controls="menu-appbar"
              aria-haspopup="true"
              onClick={handleOpenNavMenu}
              color="inherit"
            >
              <MenuIcon />
            </IconButton>
            <Menu
              id="menu-appbar"
              anchorEl={anchorElNav}
              anchorOrigin={{
                vertical: 'bottom',
                horizontal: 'left',
              }}
              keepMounted
              transformOrigin={{
                vertical: 'top',
                horizontal: 'left',
              }}
              open={Boolean(anchorElNav)}
              onClose={handleCloseNavMenu}
              sx={{
                display: { xs: 'block', md: 'none' },
              }}
            >
              {pages.map((page) => (
                <MenuItem key={page} onClick={handleCloseNavMenu}>
                  <Typography textAlign="center">{page}</Typography>
                </MenuItem>
              ))}
            </Menu>
          </Box>
          <AdbIcon sx={{ display: { xs: 'flex', md: 'none' }, mr: 1 }} />
          <Typography
            variant="h5"
            noWrap
            component="a"
            href=""
            sx={{
              mr: 2,
              display: { xs: 'flex', md: 'none' },
              flexGrow: 1,
              fontFamily: 'monospace',
              fontWeight: 700,
              letterSpacing: '.3rem',
              color: 'inherit',
              textDecoration: 'none',
            }}
          >
            LOGO
          </Typography>
          <Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
            {pages.map((page) => (
              <Button
                key={page}
                onClick={handleCloseNavMenu}
                sx={{ my: 2, color: 'white', display: 'block' }}
              >
                {page}
              </Button>
            ))}
          </Box>

          <Box sx={{ flexGrow: 0 }}>
            <Tooltip title="Open settings">
              <IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
                <Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
              </IconButton>
            </Tooltip>
            <Menu
              sx={{ mt: '45px' }}
              id="menu-appbar"
              anchorEl={anchorElUser}
              anchorOrigin={{
                vertical: 'top',
                horizontal: 'right',
              }}
              keepMounted
              transformOrigin={{
                vertical: 'top',
                horizontal: 'right',
              }}
              open={Boolean(anchorElUser)}
              onClose={handleCloseUserMenu}
            >
              {settings.map((setting) => (
                <MenuItem key={setting} onClick={handleCloseUserMenu}>
                  <Typography textAlign="center">{setting}</Typography>
                </MenuItem>
              ))}
            </Menu>
          </Box>
        </Toolbar>
      </Container>
    </AppBar>
  );
}
export default ResponsiveAppBar;

执行npm run dev时的报错信息

[plugin:vite:react-babel] /var/www/html/lnavarroa.cl/public_html/vite-app-lnavarroa/src/components/ResponsiveAppBar.jsx: Unexpected token (23:65)
 26 |   const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
/var/www/html/lnavarroa.cl/public_html/vite-app-lnavarroa/src/components/ResponsiveAppBar.jsx:23:65
21 |    const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(null);
22 |  
23 |    const handleOpenNavMenu = (event, React.MouseEvent<HTMLElement>) => {
   |                                                                   ^
24 |      setAnchorElNav(event.currentTarget);
25 |    };

问题原因

  1. 代码中使用了TypeScript类型注解(比如React.useState<null | HTMLElement>、event: React.MouseEvent<HTMLElement>),但文件后缀是.jsx,Vite默认的JavaScript环境不支持TS语法,导致babel编译报错。
  2. 报错信息显示第23行存在语法误写(逗号代替了冒号),这是复制代码时的格式问题,但核心矛盾还是TS语法在JS文件中的兼容性问题。

解决方案

方案1:切换到TypeScript环境

  • 将文件后缀从.jsx改为.tsx
  • 若项目未配置TypeScript,执行以下命令安装依赖:
    npm install typescript @types/react @types/react-dom --save-dev
    
  • Vite会自动生成tsconfig.json基础配置,无需额外手动修改(需自定义规则可调整该文件)

方案2:移除所有TypeScript类型注解

修改代码中的类型相关语法,转为纯JavaScript:

// 原代码:
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null);
const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => { ... }

// 修改后:
const [anchorElNav, setAnchorElNav] = React.useState(null);
const handleOpenNavMenu = (event) => { ... }

对所有带类型注解的代码块做同样修改即可。

为什么ButtonAppBar能正常运行?

ButtonAppBar示例代码是纯JavaScript语法,未使用TypeScript类型注解,符合Vite默认JS环境的编译规则,因此不会报错。

内容的提问来源于stack exchange,提问作者luis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:59:56