[英]TypeScript & React - one onChange Handler for multiple input fields
假设我有一个包含多个输入字段的表单。 在正常的 ES6/React 中,我会创建一个方法,所有输入字段都将指向它们的onChange
处理程序。 像这样的东西:
handleChange(e) {
e.preventDefault();
this.setState({[e.target.name]: e.target.value});
}
这在您有很多表单元素并且不必创建特定方法来处理每个元素的情况下很有帮助。
这在 TypeScript 中可能吗? 即使它不是类型安全的?
正如评论中所回答的,您可以在 JavaScript 中执行的所有操作也是有效的 TypeScript。
但是,我猜您会从 TypeScript 编译器中收到错误消息(取决于您设置的编译器选项)。
假设您的组件如下所示:
interface ComponentProps { }
interface ComponentState {
name: string
address: string
}
class MyComponent extends React.Component<ComponentProps, ComponentState> {
handleChange(e) {
e.preventDefault()
this.setState({ [e.target.name]: e.target.value })
}
}
我收到此错误:
==外部:(30,19):错误TS2345:类型'{[x:数字]的参数:任何; }' 不能分配给 'ComponentState' 类型的参数。
== 外部:类型 '{ [x: number]: any; 中缺少属性 'name' }'。
当使用noImplicitAny
编译器选项(我喜欢使用)时,这个额外的错误:
== 外部:(28,16):错误 TS7006:参数“e”隐式具有“任何”类型。
如果您确定您的代码是正确的,您可以通过显式转换handleChange
的参数和setState
的参数来handleChange
这些错误
handleChange(e: any) {
e.preventDefault()
this.setState({ [e.target.name]: e.target.value } as ComponentState)
}
我是这样解决这个问题的:
handleChange = (field: string) => (event) => {
this.setState({ [field]: event.target.value } as Pick<State, any>);
};
...
<Input onChange={this.handleChange('myField')} />
接受的答案对我不起作用。
import React, { useState } from 'react';
const Form = () => {
const [inputValues, setInputValues] = useState<{ [x: string]: string }>()
const handleFormSubmit = async (e: React.MouseEvent<HTMLElement>) => {
e.preventDefault()
const data = {
name: inputValues?.name,
email: inputValues?.email,
phone: inputValues?.phone,
income: inputValues?.name
}
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
};
try {
const response = await fetch('https://xyz/form-submit', requestOptions)
const res = await response.json()
console.log(res)
} catch (error) {
console.log(error)
}
}
const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
const { name, value } = e.currentTarget
setInputValues(prevState => ({ ...prevState, [name]: value }))
}
return (
<div className="Form">
<div className="form-wrapper">
<h1>Demo Form for React</h1>
<form className="form">
<input
className="form-input"
name="name"
value={inputValues?.name || ''}
onChange={handleInputChange}
placeholder="Your Name"
type="text"
data-testid="form-input-name"
/>
<input
className="form-input"
name="phone"
value={inputValues?.phone || ''}
onChange={handleInputChange}
placeholder="Your Phone"
type="tel"
data-testid="form-input-phone"
/>
<input
className="form-input"
name="email"
value={inputValues?.email || ''}
onChange={handleInputChange}
placeholder="Your Email"
type="email"
data-testid="form-input-email"
/>
<input
className="form-input"
name="income"
value={inputValues?.income || ''}
onChange={handleInputChange}
placeholder="Your Annual Income"
type="number"
data-testid="form-input-income"
/>
<button
className='form-submit'
data-testid="form-submit"
onClick={handleFormSubmit}
>
Submit
</button>
</form>
</div>
</div>
);
}
export default Form;
一个示例Typescript表单。 它的特点:
onChange
处理程序 此外,使用这种方法,您不必使用@ts-ignore
, any
或对您的tsconfig
进行更改。
请随心所欲地使用它。
在界面中,您必须根据您的代码调整状态的值,即 [e.target.name] 和 e.target.value 类型字符串或任何类型的字符串。
interface formState {
//it can be (name: string address: string)
[key: string]: string;
}
handleChange(e: any) {
this.setState({
[e.target.name]: e.target.value
});
}
例如
interface LoginFormState {
//can be
//email: string
//password: string
[key: string]: string;
}
interface Props {}
class LoginForm extends React.Component<Props, LoginFormState> {
constructor(props: Props) {
super(props);
this.state = {
email: "",
password: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e: any) {
this.setState({
[e.target.name]: e.target.value
});
// console.log("email", this.state.email);
}
希望这有帮助
我认为这种方法也很容易理解:
interface FormData {
firstName?: string,
lastName?: string,
}
const [form, setForm] = useState<FormData | null>(null);
和 JSX
<input onChange={(e) => setForm({...form, firstName: e.target.value})} />
<input onChange={(e) => setForm({...form, lastName: e.target.value})} />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.