Ввод машинописного текста 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 общим, а не SyntheticEvent.currentTarget.» ).

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

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

17
Это просто не работает. value не является свойством интерфейса EventTarget
tocqueville

1
Конечно, не EventTarget, но часть HTMLInputElement. Вы можете увидеть полное определение здесь github.com/DefinentyTyped/DefinentyTyped/blob/master/types/…
Йози

1
Ой, извините, вы использовали currentTarget. В таком случае да, это работает, но вопрос был оtarget
tocqueville

1
Да, вы правы, но, как упоминалось в github.com/DefinitiTyped/DefinitiTyped/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
А если у вас несколько входов, нужно ли создавать для каждого строку?
Trevor Wood

Другой способ убедиться, что this присвоено соответствующим образом в функции handleChange, - это записать handleChange как стрелочную функцию, т.е. handleChange = (e: React.ChangeEvent <HTMLInputElement>) => {this.setState (...); }; Таким образом, больше не нужно будет использовать конструктор для привязки функции handleEvent.
tlavarea

Еще один способ справиться с this вместо использования конструктора и метода привязки - это использовать стрелочную функцию в опоре 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)} />

без ошибок компиляции. Фактически, вы также можете использовать первые два интерфейса выше для других ваших компонентов.


Тип значения не является строкой!
Roger Gusmao

7

повезло, я нашел решение. ты можешь

импортировать {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оператор using использует определенные интерфейсы в соответствии с контекстом, как в этом случае мы используем HTMLInputElementдля поля ввода другие интерфейсы HTMLButtonElementи HTMLImageElementт. Д.

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

Для получения дополнительной информации вы можете проверить другой доступный интерфейс здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.