Ketikan: Jenis acara React

131

Apa tipe yang benar untuk event React. Awalnya saya hanya menggunakannya anydemi kesederhanaan. Sekarang, saya mencoba untuk membersihkan semuanya dan menghindari penggunaan anysepenuhnya.

Jadi dalam bentuk yang sederhana seperti ini:

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

Jenis apa yang saya gunakan di sini sebagai jenis acara?

React.SyntheticEvent<EventTarget>sepertinya tidak berfungsi karena saya mendapatkan kesalahan itu namedan valuetidak ada target.

Jawaban yang lebih umum untuk semua acara akan sangat dihargai.

Terima kasih

r.sendecky
sumber

Jawaban:

146

The SyntheticEvent antarmuka generik:

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

Dan itu currentTargetadalah perpotongan dari batasan umum dan EventTarget.
Selain itu, karena kejadian Anda disebabkan oleh elemen masukan, Anda harus menggunakan FormEvent( dalam file definisi , dokumen react ).

Seharusnya:

update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
}
Nitzan Tomer
sumber
15
Di mana tempat yang bagus untuk membaca tentang semua jenis acara umum? Tidak dapat menemukan di mana pun.
r.sendecky
3
Jenis acara React? Semuanya dijelaskan di halaman acara di dokumen .
Nitzan Tomer
3
Saya mendapatkan 'nama' tidak ada pada jenis 'EventTarget & HTMLInputElements' (TS v2.4)
Falieson
4
Ini masih memberi saya kesalahan berikut. "Nilai 'properti' tidak ada di jenis 'EventTarget & HTMLInputElement'."
tomhughes
1
@CMCDragonkai Saya rasa itu e.keyhanya bagian dari acara keyboard.
Nitzan Tomer
32

Masalahnya bukan pada tipe Peristiwa, tetapi antarmuka EventTarget di skrip tipe hanya memiliki 3 metode:

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

Jadi itu benar namedan valuetidak ada di EventTarget. Yang perlu Anda lakukan adalah mentransmisikan target ke jenis elemen tertentu dengan properti yang Anda butuhkan. Dalam hal ini akan terjadi HTMLInputElement.

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

Juga untuk acara bukannya React.SyntheticEvent, Anda juga dapat mengetik mereka sebagai berikut: Event, MouseEvent, KeyboardEvent... dll, tergantung pada kasus penggunaan pawang.

Cara terbaik untuk melihat semua definisi tipe ini adalah dengan memeriksa file .d.ts dari kedua skrip & react.

Lihat juga tautan berikut untuk penjelasan lebih lanjut: Mengapa Event.target bukan Elemen di Skrip Ketik?

Edwin
sumber
2
ps. Sepertinya file definisi tipe saya agak ketinggalan jaman karena tidak menampilkan antarmuka <T> SyntheticEvent generik. Jawaban dari Nitzan Tomer lebih baik.
Edwin
Ya, jawaban Nitzan sepertinya lebih bersih. Terima kasih atas usahanya.
r.sendecky
26

Untuk menggabungkan jawaban Nitzan dan Edwin, saya menemukan bahwa sesuatu seperti ini berhasil untuk saya:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
cham
sumber
1
this.props.login [target.name] = target.value; ??? apakah Anda mengubah alat peraga: o
Marwen Trabelsi
Hanya menyalin baris dari pertanyaan awal agar jawabannya masuk akal bagi OP.
cham
21

Menurut saya cara yang paling sederhana adalah:

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 The Bright
sumber
Ini berhasil untuk saya.
Benyam Ephrem
1
.ChangeEventadalah kuncinya bagi saya
Skyy2010
4

Anda dapat melakukan seperti ini dalam bereaksi

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
sumber