Input dattiloscritto onchange event.target.value


142

Nel mio reagire e app dattiloscritto, io uso: onChange={(e) => data.motto = (e.target as any).value}.

Come definisco correttamente le tipizzazioni per la classe, quindi non dovrei scavalcare il sistema di tipi con any?

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

}

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

Se lo metto target: { value: string };ottengo:

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'.

Risposte:


243

Generalmente i gestori di eventi dovrebbero usare e.currentTarget.value, ad esempio:

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

Puoi leggere il motivo per cui qui ( Ripristina "Rendi SyntheticEvent.target generico, non SyntheticEvent.currentTarget." ).

UPD: come menzionato da @ roger-gusmao ChangeEventpiù adatto per la digitazione di eventi di moduli.

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

17
Questo semplicemente non funziona. value non è una proprietà dell'interfaccia EventTarget
tocqueville

1
Ovviamente non EventTarget, ma parte di HTMLInputElement Puoi vedere la definizione completa qui github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…
Yozi

1
Oh scusa, hai usato currentTarget. In quel caso sì, funziona, ma la domanda eratarget
tocqueville

1
Sì, hai ragione, ma come menzionato in github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 usando targeterrato nella maggior parte dei casi. Inoltre, l'obiettivo non deve Tcostringerci a scrivere correttamente
Yozi

1
Questo non ha funzionato per me, ho dovuto lanciare l'evento React.ChangeEvent<HTMLInputElement>piuttosto che un FormEvent.
Oblivionkey3,

86

il modo corretto di usare in TypeScript è

  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} />
        ...
    );
  }

Segui la lezione completa, è meglio capire:

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;

3
nota: per assicurarsi che i tipi siano disponibili, aggiungi lib: ["dom"]a compilerOptionsintsconfig.json
James Conkling

1
@JamesConkling Grazie mille!
Alexandre Rivest,

1
E se hai più input, devi creare una riga per ciascuno?
Trevor Wood,

Un altro modo per assicurarsi che "this" sia assegnato in modo appropriato nella funzione handleChange sarebbe quello di scrivere handleChange come una funzione freccia, ad esempio handleChange = (e: React.ChangeEvent <HTMLInputElement>) => {this.setState (...); }; In questo modo, non si dovrebbe più utilizzare il costruttore per associare la funzione handleEvent.
Tlavarea,

Un altro modo per gestire 'questo' invece di usare il metodo di costruzione e associazione sarebbe quello di usare la funzione freccia nel prop onChange cioè onChange = {e => this.handleChange (e)}
tlavarea


9

Il targettentativo di aggiunta InputPropsnon è lo stesso targetdesideratoReact.FormEvent

Quindi, la soluzione che ho potuto trovare è stata l'estensione dei tipi relativi all'evento per aggiungere il tipo di destinazione, come:

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

Una volta che hai queste classi, puoi usare il tuo componente di input come

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

senza errori di compilazione. In effetti, puoi anche usare le prime due interfacce sopra per gli altri componenti.


Il tipo di valore non è stringa!
Roger Gusmao,

7

fortunata trovo una soluzione. Puoi

importare {ChangeEvent} da 'reagire';

e quindi scrivere codice come: e:ChangeEvent<HTMLInputElement>


2

Ecco un modo con la distruzione di oggetti ES6, testato con TS 3.3.
Questo esempio è per un input di testo.

name: string = '';

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

1

Questo è quando lavori con un FileListoggetto:

onChange={(event: React.ChangeEvent<HTMLInputElement>): void => {
  const fileListObj: FileList | null = event.target.files;
  if (Object.keys(fileListObj as Object).length > 3) {
    alert('Only three images pleaseeeee :)');
  } else {
    // Do something
  }

  return;
}}

1
  function handle_change(
    evt: React.ChangeEvent<HTMLInputElement>
  ): string {
    evt.persist(); // This is needed so you can actually get the currentTarget
    const inputValue = evt.currentTarget.value;

    return inputValue
  }

E assicurati di averlo "lib": ["dom"]nel tuo tsconfig.


1

Quando si utilizza il componente figlio Controlliamo il tipo in questo modo.

Componente principale:

export default () => {

  const onChangeHandler = ((e: React.ChangeEvent<HTMLInputElement>): void => {
    console.log(e.currentTarget.value)
  }

  return (
    <div>
      <Input onChange={onChangeHandler} />
    </div>
  );
}

Componente figlio:

type Props = {
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
}

export Input:React.FC<Props> ({onChange}) => (
  <input type="tex" onChange={onChange} />
)

0

Un'alternativa che non è stata ancora menzionata è quella di digitare la funzione onChange invece degli oggetti di scena che riceve. Utilizzando React.ChangeEventHandler:

const stateChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    console.log(event.target.value);
};

-1

Grazie @haind

Sì ha HTMLInputElementfunzionato per il campo di input

//Example
var elem = e.currentTarget as HTMLInputElement;
elem.setAttribute('my-attribute','my value');
elem.value='5';

Questa HTMLInputElementinterfaccia è ereditata da HTMLElementcui è ereditata EventTargeta livello di root. Pertanto possiamo affermare di utilizzare l' asoperatore per utilizzare interfacce specifiche in base al contesto come in questo caso che stiamo usando HTMLInputElementper il campo di input che possono essere altre interfacce HTMLButtonElement, HTMLImageElementecc.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement

Per ulteriori riferimenti è possibile controllare altre interfacce disponibili qui

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.