Typescript入力onchange event.target.value


142

私の反応とタイプスクリプトアプリでは、次を使用します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'.

回答:


243

通常、イベントハンドラはを使用する必要がありますe.currentTarget.value。例:

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

理由はここで読むことができます(「SyntheticEvent.currentTargetではなくSyntheticEvent.targetをジェネリックにする」を元に戻します)。

UPD:@ roger-gusmaoが述べたように、ChangeEventフォームイベントの入力に適しています。

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

17
これは単に機能しません。値は、
EventEvent

1
もちろんないのEventTarget、しかし、あなたがここに完全な定義を見ることができHTMLInputElementの一部のgithub.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/...
Yozi

1
ああ、ごめんなさいcurrentTarget。その場合はい、それは機能しますが、問題は約target
でした

1
はい、あなたは正しい、しかしで述べたようgithub.com/DefinitelyTyped/DefinitelyTyped/pull/12239使用してtarget、ほとんどの場合、正しくありません。さらに、ターゲットはT私たちに正しく書くことを強制する必要はありません
Yozi

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"]compilerOptionstsconfig.json
ジェームズConkling

1
@JamesConklingありがとうございます!
Alexandre Rivest

1
そして、複数の入力がある場合、それぞれに行を作成する必要がありますか?
Trevor Wood

「this」がhandleChange関数で適切に割り当てられていることを確認する別の方法は、handleChangeを矢印関数として記述することです。つまり、handleChange =(e:React.ChangeEvent <HTMLInputElement>)=> {this.setState(...); }; そうすることで、handleEvent関数をバインドするためにコンストラクターを使用する必要がなくなります。
tlavarea

コンストラクターとバインドメソッドを使用する代わりに「this」を処理するもう1つの方法は、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)} />

コンパイルエラーなし。実際、上記の最初の2つのインターフェースを他のコンポーネントに使用することもできます。


値のタイプは文字列ではありません!
Roger Gusmao

7

幸運なことに私は解決策を見つけました。あなたはできる

import 'ChangeEvent} from' react ';

次に、次のようなコードを記述します。 e:ChangeEvent<HTMLInputElement>


2

これは、TS 3.3でテストされたES6オブジェクトの構造解除の方法です。
この例はテキスト入力用です。

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他のインターフェイスができる入力フィールドのためHTMLButtonElementHTMLImageElement

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

詳細については、他の利用可能なインターフェースをここで確認できます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.