Typographie: types d'événements React

131

Quel est le type correct pour les événements React. Au départ, je l'ai juste utilisé anypar souci de simplicité. Maintenant, j'essaie de nettoyer les choses et d'éviter anycomplètement l' utilisation .

Donc, sous une forme simple comme celle-ci:

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

Quel type dois-je utiliser ici comme type d'événement?

React.SyntheticEvent<EventTarget>ne semble pas fonctionner comme je reçois une erreur nameet valuen'existe pas sur target.

Une réponse plus générale pour tous les événements serait vraiment appréciée.

Merci

r.sendecky
la source

Réponses:

146

L' interface SyntheticEvent est générique:

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

Et le currentTargetest une intersection de la contrainte générique et EventTarget.
De plus, puisque vos événements sont causés par un élément d'entrée, vous devez utiliser le FormEvent( dans le fichier de définition , les documents react ).

Devrait être:

update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
}
Nitzan Tomer
la source
15
Quel est le bon endroit pour lire sur tous les types d'événements courants? Impossible de trouver n'importe où.
r.sendecky
3
Réagir les types d'événements? Ils sont tous décrits dans la page des événements de la documentation .
Nitzan Tomer
3
J'obtiens que 'nom' n'existe pas sur le type 'EventTarget & HTMLInputElements' (TS v2.4)
Falieson
4
Cela me donne toujours l'erreur suivante. "La propriété 'value' n'existe pas sur le type 'EventTarget & HTMLInputElement'."
tomhughes
1
@CMCDragonkai Je pense que ce e.keyn'est qu'une partie des événements de clavier.
Nitzan Tomer
32

Le problème ne vient pas du type Event, mais que l'interface EventTarget en typographie n'a que 3 méthodes:

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

Il est donc correct nameet valuen'existe pas sur EventTarget. Ce que vous devez faire est de convertir la cible dans le type d'élément spécifique avec les propriétés dont vous avez besoin. Dans ce cas, ce sera le cas HTMLInputElement.

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

De plus pour les événements au lieu de React.SyntheticEvent, vous pouvez également les saisir comme suit: Event, MouseEvent, KeyboardEvent... etc, dépend du cas d'utilisation du gestionnaire.

La meilleure façon de voir toutes ces définitions de type est d'extraire les fichiers .d.ts à la fois du texte et de réagir.

Consultez également le lien suivant pour plus d'explications: Pourquoi Event.target n'est-il pas un élément dans Typescript?

Edwin
la source
2
ps. ressemble à mon fichier de définition de type est un peu obsolète car il ne montre pas l'interface générique SyntheticEvent <T>. La réponse de Nitzan Tomer est meilleure.
Edwin
Oui, la réponse de Nitzan semble plus claire. Merci pour l'effort.
r.sendecky
26

Pour combiner les réponses de Nitzan et d'Edwin, j'ai trouvé que quelque chose comme ça fonctionne pour moi:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
cham
la source
1
this.props.login [target.name] = target.value; ??? changez-vous les accessoires: o
Marwen Trabelsi
Copiez simplement la ligne de la question originale pour que la réponse ait un sens pour l'OP.
cham
21

Je pense que le moyen le plus simple est que:

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();
}
Serg le brillant
la source
Cela l'a fait pour moi.
Benyam Ephrem
1
.ChangeEventétait la clé pour moi
Skyy2010
4

tu peux faire comme ça en réagissant

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
}
Chandan Kumar
la source