타이프 스크립트 입력 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
이것은 단순히 작동하지 않습니다. value는 인터페이스 EventTarget
tocqueville

1
물론 EventTarget이 아니라 HTMLInputElement의 일부 github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/…
Yozi

1
아 죄송합니다 currentTarget. 이 경우에, 그렇습니다. 그러나 문제는target
tocqueville

1
네, 바로,하지만에서 언급 한 바와 같이 github.com/DefinitelyTyped/DefinitelyTyped/pull/12239 사용하여 target대부분의 경우 잘못된. 더욱이, 목표는 T우리가 정확하게 쓰도록 강요 할 필요가 없습니다
Yozi

1
이것은 나를 위해 작동하지 않았다, 나는 이벤트를 React.ChangeEvent<HTMLInputElement>FormEvent 대신 에 캐스트해야했다 .
Oblivionkey3 3

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
James Conkling

1
@JamesConkling 정말 감사합니다!
Alexandre Rivest

1
그리고 입력이 여러 개인 경우 각각에 대해 행을 만들어야합니까?
Trevor Wood

handleChange 함수에 'this'가 올바르게 지정되도록하는 또 다른 방법은 handleChange를 화살표 함수로 작성하는 것입니다. 즉 handleChange = (e : React.ChangeEvent <HTMLInputElement>) => {this.setState (...); }; 그렇게하면 더 이상 handleEvent 함수를 바인딩하기 위해 생성자를 사용할 필요가 없습니다.
tlavarea

생성자와 bind 메소드를 사용하는 대신 'this'를 처리하는 또 다른 방법은 onChange prop에서 화살표 함수를 사용하는 것입니다. 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

운이 좋은 해결책을 찾으십시오. 당신은 할 수 있습니다

'react'에서 {ChangeEvent} 가져 오기;

다음과 같은 코드를 작성하십시오. 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

Child Component를 사용할 때 이와 같은 타입을 확인합니다.

부모 구성 요소 :

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

아직 언급되지 않은 대안은 수신되는 prop 대신 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

자세한 내용은 여기에서 사용 가능한 다른 인터페이스를 확인할 수 있습니다

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.