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

React+Material-UI菜单点击报错:Type 'void'无法赋值给点击事件类型

解决Material-UI Menu中onClick的TypeScript类型错误

嘿,我一眼就看出问题所在啦!你遇到的这个Type 'void' is not assignable to type '(event: MouseEvent<HTMLDivElement, MouseEvent>) => void'错误,核心原因是你直接执行了函数,而不是给onClick传递一个函数引用。

错误原因拆解

你现在写的是:

<div onClick={handleClose(languages[0])}>{languages[0]}</div>

这里handleClose(languages[0])会在组件渲染时立即执行,而handleClose内部只调用了setLanguage,没有返回任何值(也就是返回void)。但onClick需要的是一个能接收鼠标事件参数的函数类型,所以TypeScript直接报错了。

两种修复方案

方案1:用箭头函数包裹(最简单直接)

把直接调用的函数改成箭头函数,这样onClick拿到的是一个待执行的函数,只有点击时才会触发handleClose:

<div onClick={() => handleClose(languages[0])}>{languages[0]}</div>
<div onClick={() => handleClose(languages[1])}>{languages[1]}</div>
<div onClick={() => handleClose(languages[2])}>{languages[2]}</div>

方案2:让handleClose返回一个函数(更灵活,适合需要用到event的场景)

修改handleClose的结构,让它先接收语言参数,再返回一个处理事件的函数:

const handleClose = (word: string) => {
  return (event: React.MouseEvent<HTMLDivElement>) => {
    // 如果需要用到event对象,比如阻止冒泡,就可以在这里用
    // event.stopPropagation();
    setLanguage(word);
  };
};

这样你原来的onClick={handleClose(languages[0])}写法就完全合法了,因为handleClose(languages[0])会返回一个符合要求的事件处理函数。

额外优化:用Material-UI的MenuItem组件(更规范)

其实Material-UI的Menu组件搭配MenuItem使用才是标准做法,MenuItem内置了点击反馈、菜单关闭逻辑等,比自己写div更省心。另外你原来的Menu的onClose也有问题(因为它需要的是关闭菜单的逻辑,不是设置语言的逻辑),我们可以把逻辑拆分得更清晰:

import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import React, { useState } from 'react'; // 别忘了导入useState

export default function SimpleMenu() {
  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
  const [language, setLanguage] = useState('English');
  const languages = ['English', 'Chinese ( Simplified )', 'Chinese ( Traditional )'];

  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    setAnchorEl(event.currentTarget);
  };

  // 单独处理菜单关闭
  const handleMenuClose = () => {
    setAnchorEl(null);
  };

  // 处理语言选择,同时关闭菜单
  const handleLanguageSelect = (word: string) => {
    setLanguage(word);
    handleMenuClose();
  };

  return (
    <div>
      <Button aria-controls="simple-menu" aria-haspopup="true" onClick={handleClick}>
        {language} {/* 这里可以显示当前选中的语言,更友好 */}
      </Button>
      <Menu
        id="simple-menu"
        anchorEl={anchorEl}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleMenuClose}
      >
        {languages.map((lang) => (
          <MenuItem key={lang} onClick={() => handleLanguageSelect(lang)}>
            {lang}
          </MenuItem>
        ))}
      </Menu>
    </div>
  );
}

这里我还加了用map渲染菜单选项的写法,避免重复代码,同时把按钮文字改成当前选中的语言,体验更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:22:49