typescript:react事件类型

IT技术 javascript reactjs typescript
2021-02-12 05:25:26

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并且valuetarget.

对所有事件的更概括的答案将不胜感激。

谢谢

6个回答

SyntheticEvent接口是通用的:

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

(从技术上讲,该currentTarget属性位于父BaseSyntheticEvent类型上。)

而且currentTarget是通用约束和的交集 EventTarget
此外,由于您的事件是由输入元素引起的,您应该使用ChangeEvent在定义文件中react 文档)。

应该:

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

(注意:此答案最初建议使用React.FormEvent。评论中的讨论与此建议有关,但React.ChangeEvent应按如上所示使用。)

我得到类型“EventTarget & HTMLInputElements”(TS v2.4)上不存在“名称”
2021-03-24 05:25:26
@CMCDragonkai 我认为这e.key只是键盘事件的一部分。
2021-03-29 05:25:26
这仍然给我以下错误。“'EventTarget & HTMLInputElement' 类型不存在属性 'value'。”
2021-04-06 05:25:26
反应事件类型?它们都在文档事件页面中进行了描述
2021-04-07 05:25:26
什么是阅读所有常见事件类型的好地方?找不到任何地方。
2021-04-09 05:25:26

问题不在于 Event 类型,而在于 typescript 中的 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...等,取决于处理程序的用例。

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

另请查看以下链接以获取更多解释: Why is Event.target not Element in Typescript?

附:看起来我的类型定义文件有点过时,因为它没有显示通用 SyntheticEvent<T> 接口。Nitzan Tomer 的回答更好。
2021-03-30 05:25:26

结合 Nitzan 和 Edwin 的答案,我发现这样的事情对我有用:

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
只需复制原始问题中的行,以便答案对 OP 有意义。
2021-03-20 05:25:26
this.props.login[target.name] = target.value; ???你在换道具吗:o
2021-04-09 05:25:26

我认为最简单的方法是:

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

更新:event: React.ChangeEvent 提交:event: React.FormEvent 点击:event: React.MouseEvent

当我省略事件类型时,我的 ts-react starter 编译器没有抱怨,编译器的这种行为正常吗?谢谢。
2021-04-13 05:25:26