打字稿:反应事件类型

r.s*_*cky 91 javascript typescript reactjs

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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我在这里使用什么类型的事件类型?

React.SyntheticEvent<EventTarget>似乎没有工作,因为我得到一个错误,name并且value不存在target.

所有活动的更广泛的答案将非常感激.

谢谢

Nit*_*mer 115

SyntheticEvent接口是通用的:

interface SyntheticEvent<T> {
    ...
    currentTarget: EventTarget & T;
    ...
}
Run Code Online (Sandbox Code Playgroud)

并且currentTarget是通用约束和EventTarget.的交集 .
此外,由于您的事件是由输入元素引起的,因此您应该使用FormEvent(在定义文件中,反应文档).

应该:

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

  • 阅读所有常见事件类型的好地方是什么?无法找到任何地方. (10认同)
  • 这仍然给我以下错误."EventTarget和HTMLInputElement"类型中不存在"属性'值'." (4认同)
  • 反应事件类型?它们都在文档的[事件页面](https://facebook.github.io/react/docs/events.html)中进行了描述。 (3认同)
  • 我在'EventTarget&HTMLInputElements'(TS v2.4)类型中不存在'name' (3认同)

Edw*_*win 22

问题不在于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;
}
Run Code Online (Sandbox Code Playgroud)

所以在EventTarget中存在name并且value不存在是正确的.您需要做的是将目标强制转换为具有所需属性的特定元素类型.在这种情况下它将是HTMLInputElement.

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

另外对于事件,而不是React.SyntheticEvent,你也可以输入他们如下:Event,MouseEvent,KeyboardEvent...等,取决于处理程序的使用情况.

查看所有这些类型定义的最佳方法是从两个打字稿中检出.d.ts文件并做出反应.

另请查看以下链接以获取更多解释: 为什么Event.target不是Typescript中的元素?

  • PS.看起来我的类型定义文件有点过时,因为它没有显示通用的SyntheticEvent <T>接口.Nitzan Tomer的答案更好. (2认同)

cha*_*ham 17

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

update = (e: React.FormEvent<EventTarget>): void => {
    let target = e.target as HTMLInputElement;
    this.props.login[target.name] = target.value;
}
Run Code Online (Sandbox Code Playgroud)

  • this.props.login[目标.名称] = 目标.值; ??? 你在改变道具吗:o (3认同)

小智 16

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


Bea*_*ith 13

types.ts我在html 输入、选择和文本区域的文件中有以下内容:

export type InputChangeEventHandler = React.ChangeEventHandler<HTMLInputElement>
export type TextareaChangeEventHandler = React.ChangeEventHandler<HTMLTextAreaElement>
export type SelectChangeEventHandler = React.ChangeEventHandler<HTMLSelectElement>
Run Code Online (Sandbox Code Playgroud)

然后导入它们:

import { InputChangeEventHandler } from '../types'
Run Code Online (Sandbox Code Playgroud)

然后使用它们:


const updateName: InputChangeEventHandler = (event) => {
  // Do something with `event.currentTarget.value`
}
const updateBio: TextareaChangeEventHandler = (event) => {
  // Do something with `event.currentTarget.value`
}
const updateSize: SelectChangeEventHandler = (event) => {
  // Do something with `event.currentTarget.value`
}
Run Code Online (Sandbox Code Playgroud)

然后将函数应用到您的标记上(替换...为其他必要的道具):

<input onChange={updateName} ... />
<textarea onChange={updateName} ... />
<select onChange={updateSize} ... >
  // ...
</select>
Run Code Online (Sandbox Code Playgroud)

  • 我想这取决于你想要做什么(这很令人困惑),但对我来说,我必须将其更改为“导出类型 InputChangeEventHandler = React.ChangeEvent&lt;HTMLInputElement&gt;;”才能使用“event.target.value”。使用 `ChangeEventHandler` 不允许使用 `event.target`,因为它是未定义的。 (2认同)

小智 10

我认为最简单的方法是:

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();
}
Run Code Online (Sandbox Code Playgroud)


小智 10

你可以在反应中这样做

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
}
Run Code Online (Sandbox Code Playgroud)


Jua*_*rce 10

这是 2022 年 Typescript 编译器的推荐方式:

const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
      console.log('click');
 };
Run Code Online (Sandbox Code Playgroud)

无需添加 void 作为返回值,因为这是由编译器自动完成的。