admin管理员组文章数量:1128975
What is the correct type for React events?
Initially I just used any
for the sake of simplicity. Now, I am trying to clean things up and avoid use of any
completely.
So in a simple form like this:
export interface LoginProps {
login: {
[k: string]: string | Function
uname: string
passw: string
logIn: Function
}
}
@inject('login') @observer
export class Login extends Component<LoginProps, {}> {
update = (e: React.SyntheticEvent<EventTarget>): void => {
this.props.login[e.target.name] = e.target.value
}
submit = (e: any): void => {
this.props.login.logIn()
e.preventDefault()
}
render() {
const { uname, passw } = this.props.login
return (
<div id='login' >
<form>
<input
placeholder='Username'
type="text"
name='uname'
value={uname}
onChange={this.update}
/>
<input
placeholder='Password'
type="password"
name='passw'
value={passw}
onChange={this.update}
/>
<button type="submit" onClick={this.submit} >
Submit
</button>
</form>
</div>
)
}
}
What type do I use here as event type?
React.SyntheticEvent<EventTarget>
does not seem to be working as I get an error that name
and value
do not exist on target
.
More generalised answer for all events would be really appreciated.
Thanks
What is the correct type for React events?
Initially I just used any
for the sake of simplicity. Now, I am trying to clean things up and avoid use of any
completely.
So in a simple form like this:
export interface LoginProps {
login: {
[k: string]: string | Function
uname: string
passw: string
logIn: Function
}
}
@inject('login') @observer
export class Login extends Component<LoginProps, {}> {
update = (e: React.SyntheticEvent<EventTarget>): void => {
this.props.login[e.target.name] = e.target.value
}
submit = (e: any): void => {
this.props.login.logIn()
e.preventDefault()
}
render() {
const { uname, passw } = this.props.login
return (
<div id='login' >
<form>
<input
placeholder='Username'
type="text"
name='uname'
value={uname}
onChange={this.update}
/>
<input
placeholder='Password'
type="password"
name='passw'
value={passw}
onChange={this.update}
/>
<button type="submit" onClick={this.submit} >
Submit
</button>
</form>
</div>
)
}
}
What type do I use here as event type?
React.SyntheticEvent<EventTarget>
does not seem to be working as I get an error that name
and value
do not exist on target
.
More generalised answer for all events would be really appreciated.
Thanks
Share Improve this question edited Dec 16, 2022 at 7:56 Kye 4,4953 gold badges24 silver badges49 bronze badges asked Feb 7, 2017 at 4:06 r.sendeckyr.sendecky 10.3k10 gold badges41 silver badges63 bronze badges 011 Answers
Reset to default 393The SyntheticEvent interface is generic:
interface SyntheticEvent<T> {
...
currentTarget: EventTarget & T;
...
}
(Technically the currentTarget
property is on the parent BaseSyntheticEvent type.)
And the currentTarget
is an intersection of the generic constraint and EventTarget
.
Also, since your events are caused by an input element you should use the ChangeEvent
(in definition file, the react docs).
Should be:
update = (e: React.ChangeEvent<HTMLInputElement>): void => {
this.props.login[e.currentTarget.name] = e.currentTarget.value
}
(Note: This answer originally suggested using React.FormEvent
. The discussion in the comments is related to this suggestion, but React.ChangeEvent
should be used as shown above.)
The problem is not with the Event type, but that the EventTarget interface in typescript only has 3 methods:
interface EventTarget {
addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
dispatchEvent(evt: Event): boolean;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void;
}
interface SyntheticEvent {
bubbles: boolean;
cancelable: boolean;
currentTarget: EventTarget;
defaultPrevented: boolean;
eventPhase: number;
isTrusted: boolean;
nativeEvent: Event;
preventDefault(): void;
stopPropagation(): void;
target: EventTarget;
timeStamp: Date;
type: string;
}
So it is correct that name
and value
don't exist on EventTarget. What you need to do is to cast the target to the specific element type with the properties you need. In this case it will be HTMLInputElement
.
update = (e: React.SyntheticEvent): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}
Also for events instead of React.SyntheticEvent, you can also type them as following: Event
, MouseEvent
, KeyboardEvent
...etc, depends on the use case of the handler.
The best way to see all these type definitions is to checkout the .d.ts files from both typescript & react.
Also check out the following link for more explanations: Why is Event.target not Element in Typescript?
I think the simplest way is that:
type InputEvent = React.ChangeEvent<HTMLInputElement>;
type ButtonEvent = React.MouseEvent<HTMLButtonElement>;
update = (e: InputEvent): void => this.props.login[e.target.name] = e.target.value;
submit = (e: ButtonEvent): void => {
this.props.login.logIn();
e.preventDefault();
}
To combine both Nitzan's and Edwin's answers, I found that something like this works for me:
update = (e: React.FormEvent<EventTarget>): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}
for update: event: React.ChangeEvent
for submit: event: React.FormEvent
for click: event: React.MouseEvent
I have the following in a types.ts
file for html input, select, and textarea:
export type InputChangeEventHandler = React.ChangeEventHandler<HTMLInputElement>
export type TextareaChangeEventHandler = React.ChangeEventHandler<HTMLTextAreaElement>
export type SelectChangeEventHandler = React.ChangeEventHandler<HTMLSelectElement>
Then import them:
import { InputChangeEventHandler } from '../types'
Then use them:
const updateName: InputChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}
const updateBio: TextareaChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}
const updateSize: SelectChangeEventHandler = (event) => {
// Do something with `event.currentTarget.value`
}
Then apply the functions on your markup (replacing ...
with other necessary props):
<input onChange={updateName} ... />
<textarea onChange={updateName} ... />
<select onChange={updateSize} ... >
// ...
</select>
you can do like this in react
handleEvent = (e: React.SyntheticEvent<EventTarget>) => {
const simpleInput = (e.target as HTMLInputElement).value;
//for simple html input values
const formInput = (e.target as HTMLFormElement).files[0];
//for html form elements
}
This is the recommended way as to the typescript compiler on 2022:
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
console.log('click');
};
No need to add void as return value as this is done automatically by the compiler.
For those who are looking for a solution to get an event and store something, in my case a HTML 5 element, on a useState
here's my solution:
const [anchorElement, setAnchorElement] = useState<HTMLButtonElement | null>(null);
const handleMenu = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) : void => {
setAnchorElement(event.currentTarget);
};
The following have the same type:
let event1: { target: { value: any } };
let event2: { target: HTMLInputElement } };
Or you could just use
const handles = (e: React.UIEvent<'type of element', UIEvent>) => {
//do something
}
本文标签: javascriptTypescript React event typesStack Overflow
版权声明:本文标题:javascript - Typescript: React event types - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736711463a1948966.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论