Input skrip onchange event.target.value

142

Dalam bereaksi dan app saya naskah, saya menggunakan: onChange={(e) => data.motto = (e.target as any).value}.

Bagaimana cara saya mendefinisikan typing untuk kelas dengan benar, jadi saya tidak perlu meretas jalan saya dengan sistem type any?

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

}

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

Jika saya menempatkan target: { value: string };saya mendapatkan:

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'.
mata angin
sumber

Jawaban:

243

Umumnya penangan acara harus menggunakan e.currentTarget.value, misalnya:

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

Anda dapat membaca mengapa demikian di sini ( Kembalikan "Jadikan SyntheticEvent.target generik, bukan SyntheticEvent.currentTarget." ).

UPD: Seperti yang disebutkan oleh @ roger-gusmao ChangeEventlebih cocok untuk mengetik acara bentuk.

onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
   const newValue = e.target.value;
}
Yozi
sumber
17
Ini sama sekali tidak bekerja. nilai bukan milik antarmuka EventTarget
tocqueville
1
Tentu saja tidak EventTarget, tetapi bagian dari HTMLInputElement Anda dapat melihat definisi lengkap di sini github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/...
Yozi
1
Oh maaf, kamu dulu currentTarget. Dalam hal itu ya, itu berhasil, tetapi pertanyaannya adalah tentangtarget
tocqueville
1
Ya, Anda benar, tetapi sebagaimana disebutkan dalam github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 menggunakan targetkesalahan dalam banyak kasus. Selain itu, target tidak harus Tmemaksa kita untuk menulis dengan benar
Yozi
1
Ini tidak berhasil untuk saya, saya harus menyerahkan acara tersebut ke React.ChangeEvent<HTMLInputElement>FormEvent.
Oblivionkey3
86

cara yang benar untuk digunakan dalam TypeScript adalah

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

Ikuti kelas lengkap, lebih baik untuk memahami:

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;
Roger Gusmao
sumber
3
catatan: untuk memastikan jenis yang tersedia, tambahkan lib: ["dom"]ke compilerOptionsdalamtsconfig.json
James Conkling
1
@JamesConkling Terima kasih banyak!
Alexandre Rivest
1
Dan jika Anda memiliki beberapa input, Anda perlu membuat baris untuk masing-masing?
Trevor Wood
Cara lain untuk memastikan 'ini' ditugaskan dengan tepat di fungsi handleChange adalah dengan menulis handleChange sebagai fungsi panah yaitu handleChange = (e: React.ChangeEvent <HTMLInputElement>) => {this.setState (...); }; Dengan melakukan itu, seseorang tidak lagi harus menggunakan konstruktor untuk mengikat fungsi handleEvent.
tlavarea
Satu lagi cara untuk menangani 'ini' daripada menggunakan metode konstruktor dan ikat adalah dengan menggunakan fungsi panah di prop onChange yaitu onChange = {e => this.handleChange (e)}
tlavarea
12

as HTMLInputElement bekerja untukku

haind
sumber
9

The targetAnda mencoba untuk menambahkan InputPropstidak sama targetAnda ingin yang diReact.FormEvent

Jadi, solusi yang dapat saya buat adalah, memperluas jenis acara terkait untuk menambahkan jenis target Anda, seperti:

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

Setelah Anda memiliki kelas-kelas itu, Anda dapat menggunakan komponen input Anda sebagai

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

tanpa kesalahan kompilasi. Bahkan, Anda juga dapat menggunakan dua antarmuka pertama di atas untuk komponen lainnya.

Leone
sumber
Jenis nilai bukan string!
Roger Gusmao
7

beruntung saya menemukan solusinya. kamu bisa

impor {ChangeEvent} dari 'react';

lalu tulis kode seperti: e:ChangeEvent<HTMLInputElement>

Linshuizhaoying
sumber
2

Berikut ini cara penghancuran objek ES6, diuji dengan TS 3.3.
Contoh ini untuk input teks.

name: string = '';

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

Ini adalah ketika Anda bekerja dengan FileListObyek:

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;
}}
Dryden Williams
sumber
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
  }

Dan pastikan Anda memiliki "lib": ["dom"]di Anda tsconfig.

longsoran1
sumber
1

Saat menggunakan Komponen Anak Kami memeriksa jenis seperti ini.

Komponen Induk:

export default () => {

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

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

Komponen anak:

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

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

Alternatif yang belum disebutkan adalah mengetikkan fungsi onChange bukan props yang diterimanya. Menggunakan React.ChangeEventHandler:

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

Terima kasih @ haind

Ya HTMLInputElementberfungsi untuk bidang input

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

Ini HTMLInputElementadalah antarmuka yang diwarisi dari HTMLElementyang diwarisi dari EventTargetpada tingkat root. Oleh karena itu kita dapat menegaskan menggunakan asoperator untuk menggunakan antarmuka spesifik sesuai dengan konteks seperti dalam kasus ini kita gunakan HTMLInputElementuntuk bidang input antarmuka lain dapat HTMLButtonElement, HTMLImageElementdll.

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

Untuk referensi lebih lanjut Anda dapat memeriksa antarmuka lain yang tersedia di sini

Ali Jamal
sumber