Typescript: Реагувати типи подій


130

Який правильний тип подій React. Спочатку я просто використовувався anyзаради простоти. Зараз я намагаюся прибрати речі та уникати використання anyповністю.

Так у простому вигляді, як це:

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

Який тип я використовую тут як тип події?

React.SyntheticEvent<EventTarget>чи не здається , не працює , як я отримую повідомлення про помилку , що nameі valueне існує на target.

Більш узагальнена відповідь на всі події була б дуже вдячна.

Дякую

Відповіді:


146

Інтерфейс SyntheticEvent є загальним:

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

І currentTargetє перетином родового обмеження і EventTarget.
Крім того, оскільки ваші події спричинені вхідним елементом, ви повинні використовувати FormEvent( у файлі визначення , документи реагування ).

Має бути:

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

15
Що можна прочитати про всі типові події? Неможливо ніде знайти.
r.sendecky

3
Реагують типи подій? Всі вони описані на сторінці подій у документах .
Нітзан Томер

3
Я отримую "ім'я" не існує в типі "EventTarget & HTMLInputElements" (TS v2.4)
Falieson

4
Це все ще дає мені таку помилку. "Значення" властивості "не існує для типу" EventTarget & HTMLInputElement "."
tomhughes

1
@CMCDragonkai Я думаю, що e.keyце лише частина подій на клавіатурі.
Нітзан Томер

29

Проблема полягає не в типі події, а в тому, що інтерфейс EventTarget у typecript має лише 3 способи:

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

Отже, це правильно nameі valueне існує в EventTarget. Що вам потрібно зробити, це надати ціль конкретному типу елементів із потрібними вам властивостями. У цьому випадку це буде HTMLInputElement.

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

Крім того, для подій замість React.SyntheticEvent, ви можете також ввести їх в такий спосіб : Event, MouseEvent, KeyboardEvent... і т.д., в залежності від випадку використання обробника.

Найкращий спосіб переглянути всі ці типові визначення - перевірити файли .d.ts з обох типів та реагувати.

Також перегляньте наступне посилання для отримання додаткових пояснень: Чому Event.target не є елементом у Typescript?


2
пс. схоже, мій файл визначення типу трохи застарів, оскільки він не показує загальний інтерфейс SyntheticEvent <T>. Відповідь від Нітзан Томер краще.
Едвін

Так, відповідь Нітзана здається більш чистою. Дякую за зусилля.
r.sendecky

25

Щоб поєднати відповіді Нітзана та Едвіна, я виявив, що щось подібне на мене працює:

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

1
this.props.login [target.name] = target.value; ??? ти міняєш реквізит: o
Marwen Trabelsi

Просто скопіюйте рядок з оригінального питання, щоб відповідь мала сенс для ОП.
чам

21

Я думаю, що найпростіший спосіб полягає в тому, що:

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

Це зробило це для мене.
Benyam Єфрем

1
.ChangeEventбуло ключовим для мене
Skyy2010

4

ви можете зробити так, як реагувати

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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.