Kiểu chữ nhập vào trao đổi event.target.value


141

Trong ứng dụng phản ứng và bản in của tôi, tôi sử dụng : onChange={(e) => data.motto = (e.target as any).value}.

Làm cách nào để xác định chính xác các kiểu chữ cho lớp, vì vậy tôi sẽ không phải hack theo cách của mình xung quanh hệ thống loại any?

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

}

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

Nếu tôi đặt target: { value: string };tôi nhận được:

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'.

Câu trả lời:


243

Nói chung, xử lý sự kiện nên sử dụng e.currentTarget.value, ví dụ:

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

Bạn có thể tìm hiểu tại sao nó như vậy ở đây ( Hoàn nguyên "Make SyntheticEvent.target chung chung, không SyntheticEvent.currentTarget." ).

CẬP NHẬT: Như được đề cập bởi @ roger-gusmao ChangeEventphù hợp hơn cho việc gõ các sự kiện biểu mẫu.

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

17
Điều này chỉ đơn giản là không hoạt động. giá trị không phải là một tài sản của giao diện EventTarget
tocqueville

1
Tất nhiên không phải là EventTarget, nhưng là một phần của HTMLInputEuity Bạn có thể xem định nghĩa đầy đủ tại đây github.com/DefiniteTyped/DefiniteTyped/blob/master/types/iêu
Yozi

1
Oh xin lỗi, bạn đã sử dụng currentTarget. Trong trường hợp đó, nó hoạt động, nhưng câu hỏi là vềtarget
tocqueville

1
Có, bạn đúng, nhưng như đã đề cập trong github.com/DefiniteTyped/DefiniteTyped/pull/12239 sử dụng targetkhông chính xác trong hầu hết các trường hợp. Hơn nữa, mục tiêu không phải Tbuộc chúng tôi viết chính xác
Yozi

1
Điều này không hiệu quả với tôi, tôi đã phải tổ chức sự kiện React.ChangeEvent<HTMLInputElement>thay vì FormEvent.
Oblivionkey3

86

cách chính xác để sử dụng trong TypeScript là

  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} />
        ...
    );
  }

Theo dõi lớp hoàn chỉnh, tốt hơn là hiểu:

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
lưu ý: để đảm bảo loại có sẵn, thêm lib: ["dom"]vào compilerOptionstrongtsconfig.json
James Conkling

1
@JamesConkling Cảm ơn bạn rất nhiều!
Alexandre Rivest

1
Và nếu bạn có nhiều đầu vào, bạn có cần tạo một hàng cho mỗi đầu vào không?
Trevor Wood

Một cách khác để đảm bảo 'cái này' được gán một cách thích hợp trong hàm handleChange sẽ là viết handleChange dưới dạng hàm mũi tên, ví dụ: handleChange = (e: React.ChangeEvent <HTMLInputEuity>) => {this.setState (...); }; Bằng cách đó, người ta sẽ không còn phải sử dụng hàm tạo để liên kết hàm handleEvent.
tlavarea

Một cách nữa để xử lý 'cái này' thay vì sử dụng phương thức khởi tạo và phương thức liên kết là sử dụng hàm mũi tên trong onChange prop tức là onChange = {e => this.handleChange (e)}
tlavarea


9

Những targetgì bạn đã cố gắng để thêm vào InputPropskhông giống như targetbạn muốn trongReact.FormEvent

Vì vậy, giải pháp tôi có thể đưa ra là, mở rộng các loại liên quan đến sự kiện để thêm loại mục tiêu của bạn, như:

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>>;
}

Khi bạn có các lớp đó, bạn có thể sử dụng thành phần đầu vào của mình như

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

không có lỗi biên dịch. Trên thực tế, bạn cũng có thể sử dụng hai giao diện đầu tiên ở trên cho các thành phần khác của mình.


Loại giá trị không phải là chuỗi!
Roger Gusmao

7

may mắn tôi tìm thấy một giải pháp. bạn có thể

nhập {ChangeEvent} từ 'Reac';

và sau đó viết mã như: e:ChangeEvent<HTMLInputElement>


2

Đây là một cách với việc phá hủy đối tượng ES6, được thử nghiệm với TS 3.3.
Ví dụ này là cho một văn bản đầu vào.

name: string = '';

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

1

Đây là khi bạn làm việc với FileListObject:

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
  }

Và chắc chắn rằng bạn có "lib": ["dom"]trong của bạn tsconfig.


1

Khi sử dụng Thành phần con Chúng tôi kiểm tra loại như thế này.

Thành phần phụ huynh:

export default () => {

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

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

Thành phần con:

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

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

0

Một cách khác chưa được đề cập là nhập hàm onChange thay vì các đạo cụ mà nó nhận được. Sử dụng React.ChangeEventHandler:

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

-1

Cảm ơn @haind

HTMLInputElementlàm việc cho trường đầu vào

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

Đây HTMLInputElementlà giao diện được kế thừa từ HTMLElementđó được kế thừa từ EventTargetcấp gốc. Do đó, chúng tôi có thể khẳng định sử dụng astoán tử để sử dụng các giao diện cụ thể theo ngữ cảnh như trong trường hợp này, chúng tôi đang sử dụng HTMLInputElementcho trường đầu vào, các giao diện khác có thể HTMLButtonElement, HTMLImageElementv.v.

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

Để tham khảo thêm, bạn có thể kiểm tra giao diện có sẵn khác ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.