web-dev-qa-db-fra.com

Typescript: React types d'événements

Quel est le type correct pour les événements React. Au début, je viens d'utiliser any pour des raisons de simplicité. Maintenant, j'essaie de nettoyer les choses et d'éviter l'utilisation de any complètement.

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 car je reçois une erreur indiquant que name et value n'existent pas sur target.

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

Merci

83
r.sendecky

L’interface SyntheticEvent est générique:

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

Et le currentTarget est une intersection de la contrainte générique et EventTarget.
De plus, comme vos événements sont causés par un élément d’entrée, vous devez utiliser le paramètre FormEvent ( dans le fichier de définition , les documents de réaction ).

Devrait être:

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

Le problème ne vient pas du type Event, mais du fait que l'interface EventTarget dans TypeScript ne comporte 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 que name et value n'existent pas sur EventTarget. Ce que vous devez faire est de convertir la cible en un type d'élément spécifique avec les propriétés dont vous avez besoin. Dans ce cas, il s'agira de HTMLInputElement.

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

De même, 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.

Le meilleur moyen de voir toutes ces définitions de type est d'extraire les fichiers .d.ts de TypeScript & react.

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

20
Edwin

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

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

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