Hva er riktig type for React-hendelser. Til å begynne med brukte jeg bare any
for enkelhets skyld. Nå prøver jeg å rydde opp og unngå bruk av any
helt.
Så i et enkelt skjema som dette:
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>
)
}
}
Hvilken type bruker jeg her som hendelsestype?
React.SyntheticEvent<EventTarget>
ser ikke ut til å fungere, da jeg får en feilmelding om at name
og value
ikke finnes på target
.
Mer generalisert svar for alle hendelser vil bli virkelig verdsatt.
Takk for hjelpen
Grensesnittet SyntheticEvent er generisk:
interface SyntheticEvent<T> {
...
currentTarget: EventTarget & T;
...
}
Og currentTarget
er et skjæringspunkt mellom den generiske begrensningen og EventTarget
.
Siden hendelsene dine er forårsaket av et input-element, bør du også bruke FormEvent
(i definisjonsfilen, react-dokumentene).
Burde være det:
update = (e: React.FormEvent<HTMLInputElement>): void => {
this.props.login[e.currentTarget.name] = e.currentTarget.value
}
Problemet er ikke typen Event, men at grensesnittet EventTarget i typescript bare har tre metoder:
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;
}
Så det er riktig at name
og value
ikke finnes på EventTarget. Det du må gjøre, er å caste målet til den spesifikke elementtypen med de egenskapene du trenger. I dette tilfellet blir det HTMLInputElement
.
update = (e: React.SyntheticEvent): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}
I stedet for React.SyntheticEvent kan du også skrive inn hendelser på følgende måte: Event
, MouseEvent
, KeyboardEvent
...osv., avhengig av hva handleren skal brukes til.
Den beste måten å se alle disse typedefinisjonene på er å sjekke .d.ts-filene fra både typescript & react.
Sjekk også ut følgende lenke for flere forklaringer: https://stackoverflow.com/questions/28900077/why-is-event-target-not-element-in-typescript
For å kombinere både Nitzans og Edwins svar, fant jeg ut at noe slikt fungerer for meg:
update = (e: React.FormEvent<EventTarget>): void => {
let target = e.target as HTMLInputElement;
this.props.login[target.name] = target.value;
}