Typescript: tipi di eventi React


131

Qual è il tipo corretto per gli eventi React. Inizialmente l'ho usato solo anyper semplicità. Ora, sto cercando di ripulire le cose ed evitare anycompletamente l' uso di .

Quindi in una forma semplice come questa:

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>
    )
  }
}

Che tipo utilizzo qui come tipo di evento?

React.SyntheticEvent<EventTarget>non sembra funzionare perché ricevo un errore che namee valuenon esiste su target.

Una risposta più generalizzata per tutti gli eventi sarebbe davvero apprezzata.

Grazie

Risposte:


146

L' interfaccia SyntheticEvent è generica:

interface SyntheticEvent<T> {
    ...
    currentTarget: EventTarget & T;
    ...
}

Ed currentTargetè un'intersezione del vincolo generico e EventTarget.
Inoltre, poiché i tuoi eventi sono causati da un elemento di input, dovresti usare FormEvent( nel file di definizione , i documenti di reazione ).

Dovrebbe essere:

update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
}

15
Qual è un buon punto per leggere su tutti i tipi di eventi comuni? Impossibile trovare da nessuna parte.
r.sendecky

3
Tipi di eventi di reazione? Sono tutti descritti nella pagina degli eventi nei documenti .
Nitzan Tomer

3
Ottengo che "nome" non esiste nel tipo "EventTarget e HTMLInputElements" (TS v2.4)
Falieson

4
Questo mi dà ancora il seguente errore. "La proprietà" valore "non esiste nel tipo" EventTarget & HTMLInputElement "."
tomhughes

1
@CMCDragonkai Penso che e.keysia solo una parte degli eventi della tastiera.
Nitzan Tomer

32

Il problema non è con il tipo di evento, ma l'interfaccia EventTarget in dattiloscritto ha solo 3 metodi:

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;
}

Quindi è corretto namee valuenon esistono su EventTarget. Quello che devi fare è eseguire il cast del target sul tipo di elemento specifico con le proprietà di cui hai bisogno. In questo caso lo sarà HTMLInputElement.

update = (e: React.SyntheticEvent): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}

Anche per gli eventi invece di React.SyntheticEvent, è anche possibile digitare loro come segue: Event, MouseEvent, KeyboardEvent... ecc, dipende dal caso d'uso del gestore.

Il modo migliore per vedere tutte queste definizioni di tipo è controllare i file .d.ts da entrambi i dattiloscritti e reagire.

Controlla anche il seguente link per ulteriori spiegazioni: Perché Event.target non è Element in Typescript?


2
ps. sembra che il mio file di definizione del tipo sia un po 'obsoleto in quanto non mostra l'interfaccia generica SyntheticEvent <T>. La risposta di Nitzan Tomer è migliore.
Edwin

Sì, la risposta di Nitzan sembra essere più pulita. Grazie per lo sforzo.
r.sendecky

26

Per combinare le risposte di Nitzan e di Edwin, ho scoperto che qualcosa del genere funziona per me:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}

1
this.props.login [target.name] = target.value; ??? stai cambiando gli oggetti di scena: o
Marwen Trabelsi

Copiando semplicemente la riga dalla domanda originale in modo che la risposta abbia senso per l'OP.
cham

21

Penso che il modo più semplice sia questo:

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();
}

Questo lo ha fatto per me.
Benyam Ephrem,

1
.ChangeEventè stata la chiave per me
Skyy2010

4

puoi fare così 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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.