TypeScript: типы событий React

131

Какой тип подходит для событий 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.

Было бы очень полезно получить более общий ответ на все события.

Спасибо

r.sendecky
источник

Ответы:

148

Интерфейс 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 07
3
Типы событий React? Все они описаны на странице событий в документации .
Ницан Томер
3
Я получаю, что «имя» не существует для типа «EventTarget & HTMLInputElements» (TS v2.4)
Фалисон,
4
Это по-прежнему дает мне следующую ошибку. «Свойство« значение »не существует для типа« EventTarget & HTMLInputElement ».
Tomhughes 07
1
@CMCDragonkai Я думаю, что e.keyэто только часть событий клавиатуры.
Ницан Томер
32

Проблема не в типе события, а в том, что интерфейс EventTarget в машинописном тексте имеет только 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 как в typescript, так и в React.

Также перейдите по следующей ссылке для получения дополнительных объяснений: Почему Event.target не является элементом в Typescript?

Эдвин
источник
2
пс. похоже, что мой файл определения типа немного устарел, так как он не показывает общий интерфейс SyntheticEvent <T>. Ответ от Ницан Томер лучше.
Эдвин
Да, ответ Ницана кажется более чистым. Спасибо за попытку.
r.sendecky 07
26

Чтобы объединить ответы Ницана и Эдвина, я обнаружил, что у меня работает что-то вроде этого:

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
Марвен Трабелси
Просто скопируйте строку из исходного вопроса, чтобы ответ имел смысл для OP.
Чам
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 Ephrem
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
}
Чандан Кумар
источник