如何在React TypeScript中获取Ant Design按钮onClick事件的目标值?
我正在开发基于React和TypeScript的项目,使用Ant Design组件库。我需要在点击按钮时获取按钮的value值和内部文本,当前代码运行正常但存在TypeScript类型错误,且不想使用any类型,请问正确的处理方式是什么?
我的代码如下:
import { Button, message } from "antd"; import { MouseEvent } from "react"; function App() { const buttonClickEvent = (e: MouseEvent<HTMLButtonElement>) => { message.info(e.currentTarget.value); message.info(e.currentTarget.innerText); }; return ( <> <Button onClick={buttonClickEvent} value="antd"> antd button </Button> <br /> <button type="button" onClick={buttonClickEvent} value="HTML"> HTML button </button> </> ); } export default App;
出现的类型错误信息:
Type '(e: MouseEvent
) => void' is not assignable to type 'MouseEventHandler & MouseEventHandler '.
Type '(e: MouseEvent) => void' is not assignable to type 'MouseEventHandler '.
Types of parameters 'e' and 'event' are incompatible.
Type 'MouseEvent<HTMLAnchorElement, MouseEvent>' is not assignable to type 'MouseEvent<HTMLButtonElement, MouseEvent>'.
Type 'HTMLAnchorElement' is missing the following properties from type 'HTMLButtonElement': disabled, form, formAction, formEnctype, and 11 more.typescript(2322)button.d.ts(27, 5): The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & Partial<{ href: string; target?: string | undefined; onClick?: MouseEventHandler
| undefined; } & BaseButtonProps & Omit<...> & { ...; } & Omit<...>> & RefAttributes<...>'
错误原因
Ant Design的Button组件并非总是渲染为原生<button>标签,当设置href等属性时会渲染为<a>标签,因此它的onClick事件类型兼容了HTMLButtonElement和HTMLAnchorElement两种元素类型,而你的事件函数仅接受MouseEvent<HTMLButtonElement>,导致类型不匹配。
方式一:使用联合类型+类型守卫兼容两种元素
将事件参数的类型改为MouseEvent<HTMLButtonElement | HTMLAnchorElement>,再通过类型守卫判断元素类型,避免访问不存在的属性:
import { Button, message } from "antd"; import { MouseEvent } from "react"; function App() { const buttonClickEvent = (e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => { const target = e.currentTarget; // 类型守卫判断是否为拥有value属性的按钮元素 if ('value' in target) { message.info(target.value); } message.info(target.innerText); }; return ( <> <Button onClick={buttonClickEvent} value="antd"> antd button </Button> <br /> <button type="button" onClick={buttonClickEvent} value="HTML"> HTML button </button> </> ); } export default App;
方式二:利用自定义属性传递值
通过data-*自定义属性传递值,这种方式不受元素类型限制,兼容性更强:
import { Button, message } from "antd"; import { MouseEvent } from "react"; function App() { const buttonClickEvent = (e: MouseEvent<HTMLElement>) => { const target = e.currentTarget; const value = target.dataset.value; message.info(value || ''); message.info(target.innerText); }; return ( <> <Button onClick={buttonClickEvent} data-value="antd"> antd button </Button> <br /> <button type="button" onClick={buttonClickEvent} data-value="HTML"> HTML button </button> </> ); } export default App;
方式三:直接在绑定事件时传递参数(推荐)
最简洁直观的方式,直接把需要的value和文本作为参数传入事件函数,完全规避元素类型问题:
import { Button, message } from "antd"; function App() { const buttonClickEvent = (value: string, text: string) => { message.info(value); message.info(text); }; return ( <> <Button onClick={() => buttonClickEvent("antd", "antd button")}> antd button </Button> <br /> <button type="button" onClick={() => buttonClickEvent("HTML", "HTML button")}> HTML button </button> </> ); } export default App;
内容的提问来源于stack exchange,提问作者melon A

