Тип вводу onchange event.target.value


143

У моєму зреагувати і машинопис додатки, я використовую: onChange={(e) => data.motto = (e.target as any).value}.

Як правильно визначити типізацію для класу, щоб мені не довелося зламати шлях із системою типів any?

export interface InputProps extends React.HTMLProps<Input> {
...

}

export class Input extends React.Component<InputProps, {}> {
}

Якщо я покладу, target: { value: string };я отримаю:

ERROR in [default] /react-onsenui.d.ts:87:18
Interface 'InputProps' incorrectly extends interface 'HTMLProps<Input>'.
  Types of property 'target' are incompatible.
    Type '{ value: string; }' is not assignable to type 'string'.

Відповіді:


244

Як правило, обробники подій повинні використовувати e.currentTarget.value, наприклад:

onChange = (e: React.FormEvent<HTMLInputElement>) => {
    const newValue = e.currentTarget.value;
}

Ви можете прочитати, чому це так тут ( Поверніть "Зробити SyntheticEvent.target generic, а не SyntheticEvent.currentTarget." ).

UPD: Як згадував @ roger-gusmao, ChangeEventбільше підходить для введення подій форми.

onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
   const newValue = e.target.value;
}

17
Це просто не працює. значення не є властивістю інтерфейсу EventTarget
tocqueville

1
Звичайно, не EventTarget, але частина HTMLInputElement Ви можете побачити повне визначення тут github.com/DefinitelyTyped/DefinrelyTyped/blob/master/types/…
Yozi

1
О, вибачте, ви звикли currentTarget. У такому випадку так, це працює, але питання було проtarget
tocqueville

1
Так, ви маєте рацію, але як зазначено в github.com/DefinitelyTyped/DefinrelyTyped/pull/12239, використовуючи targetнеправильне в більшості випадків. Більше того, ціль не Tповинна змушувати нас писати правильно
Йозі

1
Це не спрацювало для мене, мені довелося передати подію, React.ChangeEvent<HTMLInputElement>а не FormEvent.
Oblivionkey3

86

правильним способом використання в TypeScript є

  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
        ...
        <input value={temperature} onChange={this.handleChange} />
        ...
    );
  }

Дотримуйтесь повного класу, краще зрозуміти:

import * as React from "react";

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};


interface TemperatureState {
   temperature: string;
}

interface TemperatureProps {
   scale: string;

}

class TemperatureInput extends React.Component<TemperatureProps, TemperatureState> {
  constructor(props: TemperatureProps) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  //  handleChange(e: { target: { value: string; }; }) {
  //    this.setState({temperature: e.target.value});  
  //  }


  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
    // No longer need to cast to any - hooray for react!
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature} onChange={this.handleChange} />
      </fieldset>
    );
  }
}

export default TemperatureInput;

3
Примітка: для забезпечення типи доступні, додати lib: ["dom"]до compilerOptionsвtsconfig.json
Джеймс Конклінг

1
@JamesConkling Дуже дякую!
Олександр Рівест

1
І якщо у вас є кілька входів, вам потрібно зробити рядок для кожного?
Тревор Вуд

Іншим способом переконатися, що "це" призначено належним чином у функції handleChange, буде записати handleChange як функцію стрілки, тобто handleChange = (e: React.ChangeEvent <HTMLInputElement>) => {this.setState (...); }; Роблячи це, більше не доведеться використовувати конструктор для прив'язки функції handleEvent.
tlavarea

Ще одним способом обробити "це" замість використання методу конструктора та прив'язки було б використання функції стрілки в програмі onChange, тобто onChange = {e => this.handleChange (e)}
tlavarea


9

Те, що targetви намагалися додати, InputProps- це не те, що targetви хотілиReact.FormEvent

Отже, рішення, яке я міг би придумати, було розширення типів, пов’язаних з подіями, для додавання цільового типу, як:

interface MyEventTarget extends EventTarget {
    value: string
}

interface MyFormEvent<T> extends React.FormEvent<T> {
    target: MyEventTarget
}

interface InputProps extends React.HTMLProps<Input> {
    onChange?: React.EventHandler<MyFormEvent<Input>>;
}

Після того, як у вас є ці класи, ви можете використовувати свій вхідний компонент як

<Input onChange={e => alert(e.target.value)} />

без помилок компіляції. Насправді ви також можете використовувати перші два інтерфейси вище для інших компонентів.


Тип значення не є рядком!
Роджер Гусмао

7

пощастило, я знайшов рішення. ти можеш

import {ChangeEvent} з 'реагувати';

а потім запишіть код на зразок: e:ChangeEvent<HTMLInputElement>


2

Ось спосіб деструктуризації об'єктів ES6, протестований з TS 3.3.
Цей приклад для введення тексту.

name: string = '';

private updateName({ target }: { target: HTMLInputElement }) {
    this.name = target.value;
}

1

Це коли ви працюєте з FileListоб'єктом:

onChange={(event: React.ChangeEvent<HTMLInputElement>): void => {
  const fileListObj: FileList | null = event.target.files;
  if (Object.keys(fileListObj as Object).length > 3) {
    alert('Only three images pleaseeeee :)');
  } else {
    // Do something
  }

  return;
}}

1
  function handle_change(
    evt: React.ChangeEvent<HTMLInputElement>
  ): string {
    evt.persist(); // This is needed so you can actually get the currentTarget
    const inputValue = evt.currentTarget.value;

    return inputValue
  }

І переконайтеся , що у вас є "lib": ["dom"]у вашому tsconfig.


1

Під час використання дочірнього компонента ми перевіряємо такий тип.

Батьківський компонент:

export default () => {

  const onChangeHandler = ((e: React.ChangeEvent<HTMLInputElement>): void => {
    console.log(e.currentTarget.value)
  }

  return (
    <div>
      <Input onChange={onChangeHandler} />
    </div>
  );
}

Дочірній компонент:

type Props = {
  onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
}

export Input:React.FC<Props> ({onChange}) => (
  <input type="tex" onChange={onChange} />
)

0

Альтернатива, про яку ще не було сказано, - це ввести функцію onChange замість реквізиту, який вона отримує. Використання React.ChangeEventHandler:

const stateChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    console.log(event.target.value);
};

-1

Дякую @haind

Так HTMLInputElementпрацювали для поля введення

//Example
var elem = e.currentTarget as HTMLInputElement;
elem.setAttribute('my-attribute','my value');
elem.value='5';

Це HTMLInputElementінтерфейс - HTMLElementце спадщина, від якої успадковується EventTargetна кореневому рівні. Тому ми можемо стверджувати за допомогою asоператора для використання конкретних інтерфейсів відповідно до контексту, як у цьому випадку, ми використовуємо HTMLInputElementдля поля введення інші інтерфейси HTMLButtonElement, HTMLImageElementтощо.

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement

Для більш довідкової інформації ви можете переглянути інший доступний інтерфейс тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.