繁体   English   中英

如何为setState添加包装函数?

[英]How to add a wrapper function for setState?

我在React中有一个用户注册表格,当用户名和密码文本字段的内容更改时,该表格会更新状态,例如:

<TextField onChange={e => this.updateUser(e)} />
updateUser(
  evt: React.ChangeEvent<
    HTMLTextAreaElement | HTMLInputElement | HTMLSelectElement
  >
) {
  const user = evt.target.value;
  this.setState({ user });
}

但是,我想概括化updateUser()updatePassword()函数,以便在向组件中添加更多字段时可以调用诸如updateField(e, "password")类的东西updateField(e, "password")而不是编写新函数来更新其中的每个字段。状态。

我已经试过了:

updateField(
  evt: React.ChangeEvent<
    HTMLTextAreaElement | HTMLInputElement | HTMLSelectElement
  >,
  field: string
) {
  let updatedField = {};
  updatedField[field] = evt.target.value; // error here
  this.setState(updatedField);
}

我得到的错误是

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  No index signature with a parameter of type 'string' was found on type '{}'

我没有这样做

<TextField onChange={e => this.setState({user:e.target.value})} />

因为我的更新功能实际上比我在此处粘贴的功能要多

您的尝试即将结束。 您遇到的问题是string的字段键太宽,可能是任何东西,因此类型检查器不会允许它用作状态键。 您想要的是将密钥约束为您状态的密钥。 假设您位于其中MyState是状态类型参数的Component中,则应做到这一点:

updateField<K extends keyof MyState>(
  event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement | HTMLSelectElement>,
  field: K
) {
  const { value } = event.target;
  this.setState({
    [field]: value
  } as Pick<MyProps, K>);
}

您收到此错误是因为在声明时:

let updatedField = {};

对于类型,变量updatedField具有一个空对象。 因此,当您尝试在其上设置属性时,TypeScript会告诉您您无法执行此操作,因为根据定义,空对象没有属性: 在类型“ {}”上未找到参数类型为“字符串”的索引签名

解决问题的一种简单方法是将您的代码更改为此:

updateField(
  evt: React.ChangeEvent<
    HTMLTextAreaElement | HTMLInputElement | HTMLSelectElement
  >,
  field: string
) {
  this.setState({
    [field]: evt.target.value
  });
}

这将立即创建一个具有动态“计算”属性名称(您的字段)和事件传递的值的对象,然后将其提供给setState

编辑:正如亚伦·比尔(Aaron Beall)所说,TypeScript在这里显示错误,因为计算出的属性不是您所在州类型的一部分。 你应该参考他们的答案

您可以使用高阶函数来概括更新特定字段。 这是一个示例实现:

 class ExampleForm extends React.Component { state = { name: '', password: '' } setStateFromValue = prop => ({target:{value}}) => { this.setState({[prop]: value}) } render () { return ( <form> <input onChange={this.setStateFromValue('name')} /> <input type="password" onChange={this.setStateFromValue('password')} /> <div> State: {JSON.stringify(this.state)} </div> </form> ) } } ReactDOM.render(<ExampleForm />, document.querySelector("#form")) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="form"></div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM