打字稿:React事件类型


129

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

对于所有事件的更笼统的回答,我们将不胜感激。

谢谢

Answers:


146

SyntheticEvent接口是通用的:

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

并且currentTarget是一般约束与的交集 EventTarget
另外,由于事件是由输入元素引起的,因此应使用FormEvent在定义文件中react docs)。

应该:

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

15
什么是阅读所有常见事件类型的好地方?在任何地方都找不到。
r.sendecky

3
反应事件类型?它们都在docs事件页面中进行了描述。
Nitzan Tomer

3
我在类型'EventTarget&HTMLInputElements'(TS v2.4)上不存在“名称”
Falieson

4
这仍然给我以下错误。“类型'EventTarget和HTMLInputElement'上不存在属性'值'。”
tomhughes

1
@CMCDragonkai我认为这e.key只是键盘事件的一部分。
Nitzan Tomer,

29

问题不在于事件类型,而是打字稿中的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,你也可以输入他们如下:EventMouseEventKeyboardEvent...等,取决于处理程序的使用情况。

查看所有这些类型定义的最佳方法是从typescript和react中检出.d.ts文件。

另请查看以下链接以获取更多说明: 为什么Event.target不是Typescript中的Element?


2
ps。我的类型定义文件似乎有点过时了,因为它没有显示通用的SyntheticEvent <T>接口。Nitzan Tomer的答案更好。
Edwin'2

是的,Nitzan的答案似乎更干净。感谢您的努力。
r.sendecky

25

结合Nitzan和Edwin的答案,我发现类似这样的方法对我有用:

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

只需复制原始问题中的内容,使答案对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

3

你可以这样反应

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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.