Typescript 输入 onchange event.target.value
Typescript input onchange event.target.value
在我的 React 和 TypeScript 应用程序中,我使用:
onChange={(e) => data.motto = (e.target as any).value}
如何正确定义 class 的类型,这样我就不必绕过 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'.
您尝试在 InputProps
中添加的 target
与您想要的 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)} />
没有编译错误。其实你的其他组件也可以使用上面的前两个接口。
as HTMLInputElement
适合我
一般事件处理器应该使用e.currentTarget.value
,例如:
onChange = (e: React.FormEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
}
您可以在此处阅读其中的原因 (Revert "Make SyntheticEvent.target generic, not SyntheticEvent.currentTarget.")。
UPD:如@roger-gusmao所述ChangeEvent
更适合输入表单事件。
onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
const newValue = e.target.value;
}
您可以执行以下操作:
import { ChangeEvent } from 'react';
const onChange = (e: ChangeEvent<HTMLInputElement>)=> {
const newValue = e.target.value;
}
在 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} />
...
);
}
关注完整class,更好理解:
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;
这是一种使用 ES6 对象解构的方法,已使用 TS 3.3 进行测试。
此示例用于文本输入。
name: string = '';
private updateName({ target }: { target: HTMLInputElement }) {
this.name = target.value;
}
这是当您使用 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;
}}
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
}
并确保您的 tsconfig
中有 "lib": ["dom"]
。
使用子组件时,我们会这样检查类型。
父组件:
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} />
)
尚未提及的替代方法是键入 onChange 函数而不是它接收的道具。使用 React.ChangeEventHandler:
const stateChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
console.log(event.target.value);
};
谢谢@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
等.
如需更多参考,您可以在此处查看其他可用界面
- Web API interfaces 来自 Mozilla
- Interfaces in External Node Modules 微软
我用的是这样的:
import { ChangeEvent, useState } from 'react';
export const InputChange = () => {
const [state, setState] = useState({ value: '' });
const handleChange = (event: ChangeEvent<{ value: string }>) => {
setState({ value: event?.currentTarget?.value });
}
return (
<div>
<input onChange={handleChange} />
<p>{state?.value}</p>
</div>
);
}
如果您这样做,则无需输入:
<input onChange={(event) => { setValue(e.target.value) }} />
因为如果你直接在 html 标签中用箭头函数设置一个新值,typescript 会默认理解事件的类型。
import { NativeSyntheticEvent, TextInputChangeEventData,} from 'react-native';
// Todo in java script
const onChangeTextPassword = (text : any) => {
setPassword(text);
}
// Todo in type script use this
const onChangeTextEmail = ({ nativeEvent: { text },}: NativeSyntheticEvent<TextInputChangeEventData>) => {
console.log("________ onChangeTextEmail _________ "+ text);
setEmailId(text);
};
<TextInput
style={{ width: '100%', borderBottomWidth: 1, borderBottomColor: 'grey', height: 40, }}
autoCapitalize="none"
returnKeyType="next"
maxLength={50}
secureTextEntry={false}
onChange={onChangeTextEmail}
value={emailId}
defaultValue={emailId}
/>
我们还可以使用定义类型(在功能组件中)的 onChange 事件触发,如下所示:
const handleChange = (
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
const name = e.target.name;
const value = e.target.value;
};
这对我有用,而且它与框架无关。
const handler = (evt: Event) => {
console.log((evt.target as HTMLInputElement).value))
}
在我的 React 和 TypeScript 应用程序中,我使用:
onChange={(e) => data.motto = (e.target as any).value}
如何正确定义 class 的类型,这样我就不必绕过 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'.
您尝试在 InputProps
中添加的 target
与您想要的 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)} />
没有编译错误。其实你的其他组件也可以使用上面的前两个接口。
as HTMLInputElement
适合我
一般事件处理器应该使用e.currentTarget.value
,例如:
onChange = (e: React.FormEvent<HTMLInputElement>) => {
const newValue = e.currentTarget.value;
}
您可以在此处阅读其中的原因 (Revert "Make SyntheticEvent.target generic, not SyntheticEvent.currentTarget.")。
UPD:如@roger-gusmao所述ChangeEvent
更适合输入表单事件。
onChange = (e: React.ChangeEvent<HTMLInputElement>)=> {
const newValue = e.target.value;
}
您可以执行以下操作:
import { ChangeEvent } from 'react';
const onChange = (e: ChangeEvent<HTMLInputElement>)=> {
const newValue = e.target.value;
}
在 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} />
...
);
}
关注完整class,更好理解:
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;
这是一种使用 ES6 对象解构的方法,已使用 TS 3.3 进行测试。
此示例用于文本输入。
name: string = '';
private updateName({ target }: { target: HTMLInputElement }) {
this.name = target.value;
}
这是当您使用 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;
}}
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
}
并确保您的 tsconfig
中有 "lib": ["dom"]
。
使用子组件时,我们会这样检查类型。
父组件:
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} />
)
尚未提及的替代方法是键入 onChange 函数而不是它接收的道具。使用 React.ChangeEventHandler:
const stateChange: React.ChangeEventHandler<HTMLInputElement> = (event) => {
console.log(event.target.value);
};
谢谢@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
等.
如需更多参考,您可以在此处查看其他可用界面
- Web API interfaces 来自 Mozilla
- Interfaces in External Node Modules 微软
我用的是这样的:
import { ChangeEvent, useState } from 'react';
export const InputChange = () => {
const [state, setState] = useState({ value: '' });
const handleChange = (event: ChangeEvent<{ value: string }>) => {
setState({ value: event?.currentTarget?.value });
}
return (
<div>
<input onChange={handleChange} />
<p>{state?.value}</p>
</div>
);
}
如果您这样做,则无需输入:
<input onChange={(event) => { setValue(e.target.value) }} />
因为如果你直接在 html 标签中用箭头函数设置一个新值,typescript 会默认理解事件的类型。
import { NativeSyntheticEvent, TextInputChangeEventData,} from 'react-native';
// Todo in java script
const onChangeTextPassword = (text : any) => {
setPassword(text);
}
// Todo in type script use this
const onChangeTextEmail = ({ nativeEvent: { text },}: NativeSyntheticEvent<TextInputChangeEventData>) => {
console.log("________ onChangeTextEmail _________ "+ text);
setEmailId(text);
};
<TextInput
style={{ width: '100%', borderBottomWidth: 1, borderBottomColor: 'grey', height: 40, }}
autoCapitalize="none"
returnKeyType="next"
maxLength={50}
secureTextEntry={false}
onChange={onChangeTextEmail}
value={emailId}
defaultValue={emailId}
/>
我们还可以使用定义类型(在功能组件中)的 onChange 事件触发,如下所示:
const handleChange = (
e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>
) => {
const name = e.target.name;
const value = e.target.value;
};
这对我有用,而且它与框架无关。
const handler = (evt: Event) => {
console.log((evt.target as HTMLInputElement).value))
}