web-dev-qa-db-fra.com

Entrée dactylographiée onchange event.target.value

Dans mon application de réaction et TypeScript, j'utilise: onChange={(e) => data.motto = (e.target as any).value}.

Comment définir correctement les typages pour la classe afin de ne pas avoir à me familiariser avec le système de type avec any?

export interface InputProps extends React.HTMLProps<Input> {
...

}

export class Input extends React.Component<InputProps, {}> {
}

Si je mets target: { value: string }; je reçois:

ERROR in [default] /react-onsenui.d.ts:87:18
Interface 'InputProps' incorrectly extends interface 'HTMLProps<Input>'.
  Types of property 'target' are incompatible.
    Type '{ value: string; }' is not assignable to type 'string'.
24
Cat Boss

Généralement, les gestionnaires d’événements doivent utiliser e.currentTarget.value, par exemple:

onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const newValue = e.currentTarget.value;
}

Vous pouvez lire pourquoi cela se trouve ici https://github.com/DefinitelyTyped/DefinitelyTyped/pull/12239

UPD: Comme mentionné par @ roger-gusmao ChangeEvent, il est plus approprié pour la saisie d'événements de formulaire.

onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
   const newValue = e.target.value;
}
44
Yozi

la façon correcte d'utiliser dans TypeScript est

  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
        ...
        <input value={temperature} onChange={this.handleChange} />
        ...
    );
  }

Suivez le cours complet, il vaut mieux comprendre:

import * as React from "react";

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};


interface TemperatureState {
   temperature: string;
}

interface TemperatureProps {
   scale: string;

}

class TemperatureInput extends React.Component<TemperatureProps, TemperatureState> {
  constructor(props: TemperatureProps) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  //  handleChange(e: { target: { value: string; }; }) {
  //    this.setState({temperature: e.target.value});  
  //  }


  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature} onChange={this.handleChange} />
      </fieldset>
    );
  }
}

export default TemperatureInput;
45
Roger Gusmao

as HTMLInputElement fonctionne pour moi

7
haind

La target que vous avez essayé d'ajouter dans InputProps n'est pas la même target que vous vouliez qui est dans React.FormEvent

La solution que je pouvais trouver était donc d'étendre les types liés aux événements pour ajouter votre type de cible, comme suit:

interface MyEventTarget extends EventTarget {
    value: string
}

interface MyFormEvent<T> extends React.FormEvent<T> {
    target: MyEventTarget
}

interface InputProps extends React.HTMLProps<Input> {
    onChange?: React.EventHandler<MyFormEvent<Input>>;
}

Une fois que vous avez ces classes, vous pouvez utiliser votre composant d’entrée comme

<Input onChange={e => alert(e.target.value)} />

sans erreurs de compilation. En fait, vous pouvez également utiliser les deux premières interfaces ci-dessus pour vos autres composants.

6
Leone

heureusement, je trouve une solution ... vous pouvez

importer {ChangeEvent} de 'réagir';

puis écrivez un code tel que: e:ChangeEvent<HTMLInputElement>

1
Linshuizhaoying

Voici un moyen de déstructurer les objets ES6, testé avec TS 3.3.
Cet exemple concerne une entrée de texte.

name: string = '';

private updateName({ target }: { target: HTMLInputElement }) {
    this.name = target.value;
}
0
Bap