Maszynopis: Reaguj typy zdarzeń

131

Jaki jest poprawny typ zdarzeń React. Początkowo użyłem tylko anyze względu na prostotę. Teraz próbuję wszystko uporządkować i anycałkowicie unikać używania .

A więc w prostej formie, takiej jak ta:

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

Jakiego typu używam tutaj jako typu wydarzenia?

React.SyntheticEvent<EventTarget>nie wydaje się działać jak pojawia się błąd, że namei valuenie istnieje na target.

Doceniona byłaby bardziej uogólniona odpowiedź na wszystkie wydarzenia.

Dzięki

r.sendecky
źródło

Odpowiedzi:

148

SyntheticEvent interfejs jest ogólna:

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

I currentTargetjest przecięciem ogólnego ograniczenia i EventTarget.
Ponadto, ponieważ twoje zdarzenia są powodowane przez element wejściowy, powinieneś użyć FormEvent( w pliku definicji , react docs ).

Powinien być:

update = (e: React.FormEvent<HTMLInputElement>): void => {
    this.props.login[e.currentTarget.name] = e.currentTarget.value
}
Nitzan Tomer
źródło
15
Jakie jest dobre miejsce do przeczytania o wszystkich typowych typach wydarzeń? Nie można nigdzie znaleźć.
r.sendecky
3
Reagować na typy zdarzeń? Wszystkie są opisane na stronie wydarzeń w dokumentacji .
Nitzan Tomer
3
Otrzymuję „nazwa” nie istnieje w typie „EventTarget i HTMLInputElements” (TS v2.4)
Falieson
4
To nadal daje mi następujący błąd. „Wartość właściwości” nie istnieje w typie „EventTarget & HTMLInputElement”.
tomhughes,
1
@CMCDragonkai Myślę, że e.keyto tylko część wydarzeń na klawiaturze.
Nitzan Tomer
32

Problem nie dotyczy typu zdarzenia, ale interfejs EventTarget w skrypcie ma tylko 3 metody:

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

Więc to prawda namei valuenie istnieje w EventTarget. To, co musisz zrobić, to rzutować element docelowy na określony typ elementu z potrzebnymi właściwościami. W tym przypadku tak będzie HTMLInputElement.

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

Również na imprezy zamiast React.SyntheticEvent, można również wpisać je w następujący sposób: Event, MouseEvent, KeyboardEvent... itd, zależy od przypadku korzystania z uchwytu.

Najlepszym sposobem, aby zobaczyć wszystkie te definicje typów, jest pobranie plików .d.ts z obu maszynopisów i reakcji.

Sprawdź również poniższe łącze, aby uzyskać więcej wyjaśnień: Dlaczego Event.target nie jest elementem w skrypcie?

Edwin
źródło
2
ps. wygląda na to, że mój plik definicji typu jest nieco przestarzały, ponieważ nie pokazuje ogólnego interfejsu SyntheticEvent <T>. Odpowiedź od Nitzana Tomera jest lepsza.
Edwin,
Tak, odpowiedź Nitzana wydaje się być czystsza. Dzięki za wysiłek.
r.sendecky
26

Aby połączyć odpowiedzi Nitzana i Edwina, stwierdziłem, że coś takiego działa dla mnie:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
cham
źródło
1
this.props.login [target.name] = target.value; ??? czy zmieniasz rekwizyty: o
Marwen Trabelsi
Wystarczy skopiować wiersz z pierwotnego pytania, aby odpowiedź miała sens dla PO.
cham
21

Myślę, że najprostszy sposób jest taki:

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
źródło
Zrobiło to dla mnie.
Benyam Ephrem
1
.ChangeEventbył dla mnie klucz
Skyy2010
4

możesz to zrobić w reakcji

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
źródło