Mecanografiado: Reaccionar tipos de eventos


131

¿Cuál es el tipo correcto de eventos React? Inicialmente solo lo usé anypor simplicidad. Ahora, estoy tratando de limpiar las cosas y evitar su uso por anycompleto.

Entonces, en una forma simple 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>
    )
  }
}

¿Qué tipo utilizo aquí como tipo de evento?

React.SyntheticEvent<EventTarget>no parece estar funcionando como consigo un error que namey valueno existen en target.

Se agradecería mucho una respuesta más generalizada para todos los eventos.

Gracias

Respuestas:


146

La interfaz SyntheticEvent es genérica:

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

Y currentTargetes una intersección de la restricción genérica y EventTarget.
Además, dado que sus eventos son causados ​​por un elemento de entrada, debe usar el FormEvent( en el archivo de definición , los documentos de reacción ).

Debiera ser:

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

15
¿Cuál es un buen lugar para leer sobre todos los tipos de eventos comunes? No se puede encontrar en ningún lado.
r.sendecky

3
¿Reaccionar tipos de eventos? Todos se describen en la página de eventos en los documentos .
Nitzan Tomer

3
Obtengo 'nombre' no existe en el tipo 'EventTarget & HTMLInputElements' (TS v2.4)
Falieson

4
Esto todavía me da el siguiente error. "La propiedad 'valor' no existe en el tipo 'EventTarget & HTMLInputElement'".
Tomhughes

1
@CMCDragonkai Creo que e.keyes solo una parte de los eventos de teclado.
Nitzan Tomer

32

El problema no es con el tipo de evento, sino que la interfaz EventTarget en mecanografiado solo tiene 3 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;
}

Entonces es correcto namey valueno existe en EventTarget. Lo que debe hacer es convertir el destino en el tipo de elemento específico con las propiedades que necesita. En este caso lo será HTMLInputElement.

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

También para eventos en lugar de React.SyntheticEvent, también puede escribir como siguiente: Event, MouseEvent, KeyboardEvent... etc, depende del caso de uso del manipulador.

La mejor manera de ver todas estas definiciones de tipos es verificar los archivos .d.ts tanto de mecanografiado como de reaccionar.

Consulte también el siguiente enlace para obtener más explicaciones: ¿Por qué Event.target no es Element en Typecript?


2
PD. Parece que mi archivo de definición de tipo está un poco desactualizado ya que no muestra la interfaz genérica SyntheticEvent <T>. La respuesta de Nitzan Tomer es mejor.
Edwin

Sí, la respuesta de Nitzan parece ser más limpia. Gracias por el esfuerzo.
r.sendecky

26

Para combinar las respuestas de Nitzan y Edwin, descubrí que algo como esto funciona para mí:

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; ??? ¿Estás cambiando los accesorios?: o
Marwen Trabelsi

Simplemente copiando la línea de la pregunta original para que la respuesta tenga sentido para el OP.
cham

21

Creo que la forma más sencilla es 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();
}

Esto lo hizo por mí.
Benyam Ephrem

1
.ChangeEventfue la clave para mí
Skyy2010

4

puedes hacer esto en reaccionar

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
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.