Texto datilografado: tipos de eventos React

129

Qual é o tipo correto para eventos React. Inicialmente eu apenas usei anypor uma questão de simplicidade. Agora, estou tentando limpar as coisas e evitar o uso anycompleto.

Então, de uma forma simples como esta:

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

Que tipo eu uso aqui como tipo de evento?

React.SyntheticEvent<EventTarget>não parece estar funcionando como eu recebo um erro que namee valuenão existem no target.

Uma resposta mais generalizada para todos os eventos seria realmente apreciada.

obrigado

r.sendecky
fonte

Respostas:

145

A interface SyntheticEvent é genérica:

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

E o currentTargeté uma interseção da restrição genérica e EventTarget.
Além disso, como seus eventos são causados ​​por um elemento de entrada, você deve usar o FormEvent( no arquivo de definição , os documentos de reação ).

Deveria estar:

update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
}
Nitzan Tomer
fonte
15
Qual é um bom local para ler sobre todos os tipos de eventos comuns? Não foi possível encontrar em nenhum lugar.
precisa saber é o seguinte
3
Reagir tipos de eventos? Eles são todos descritos na página de eventos nos documentos .
Nitzan Tomer
3
Eu recebo 'name' não existe no tipo 'EventTarget & HTMLInputElements' (TS v2.4)
Falieson
4
Isso ainda me dá o seguinte erro. "A propriedade 'value' não existe no tipo 'EventTarget & HTMLInputElement'."
tomhughes
1
@CMCDragonkai Acho que isso e.keyé apenas parte dos eventos do teclado.
Nitzan Tomer
29

O problema não é com o tipo de evento, mas com a interface EventTarget em texto datilografado apenas com três métodos:

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

Portanto, é correto namee valuenão existe no EventTarget. O que você precisa fazer é converter o destino no tipo de elemento específico com as propriedades necessárias. Nesse caso, será HTMLInputElement.

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

Também para eventos em vez de React.SyntheticEvent, você também pode digitá-los da seguinte forma: Event, MouseEvent, KeyboardEvent... etc, depende do caso de uso do manipulador.

A melhor maneira de ver todas essas definições de tipo é fazer o check-out dos arquivos .d.ts do datilografado e reagir.

Verifique também o link a seguir para obter mais explicações: Por que Event.target não é elemento no texto datilografado?

Edwin
fonte
2
ps. parece que meu arquivo de definição de tipo está um pouco desatualizado, pois não mostra a interface genérica SyntheticEvent <T>. A resposta de Nitzan Tomer é melhor.
Edwin
Sim, a resposta de Nitzan parece ser mais limpa. Obrigado pelo esforço.
precisa saber é o seguinte
25

Para combinar as respostas de Nitzan e Edwin, descobri que algo assim funciona para mim:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
cham
fonte
1
this.props.login [target.name] = target.value; ??? você está alterando os adereços: o
Marwen Trabelsi
Basta copiar a linha da pergunta original para que a resposta faça sentido para o OP.
cham
21

Eu acho que a maneira mais simples é que:

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
fonte
Isso fez por mim.
Benyam Ephrem
1
.ChangeEventfoi a chave para mim
Skyy2010
3

você pode fazer assim em reagir

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
fonte