在React中受控和非受控的表单输入并不需要太复杂

时间:2022-03-23 15:20:12

原文:(https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/)

你也许在很多文章中看到过说“you shouldn’t use setState…”或者声称“refs are bad”…这是很矛盾的事。这让我们很难理解怎么才能正确取值甚至说选择的标准到底是什么。
你会认为到底应该怎么操作表单?
毕竟,表单事很多web应用程序的核心。并且,react中操作表单似乎是一种基础操作?
不要担心,让我告诉你这些方法之间的差异,以及应该如何使用。

非受控组件

非受控组件的输入框类似于传统的表单输入

class Form extends Component {
render() {
return (
<div>
<input type="text" />
</div>
);
}
}

它能够记住你输入了什么,你可以使用一个ref来获取它的值。例如,一个按钮的onClick操作:

class Form extends Component {
handleSubmitClick = () => {
const name = this._name.value;
}
render() {
return (
<div>
<input type="text" ref={input => this._name = input} />
<button onClick={this.handleSubmitClick}>Sign up</button>
</div>
);
}
}

不同的是,当你需要的时候,你就必须从这个区域里“拉取”值。通常发生在表单提交的时候。

这是实现表单输入的最简单的方式。在现实世界中学习使用react操作简单的表单时,这无疑是一个很有效的使用方法。

不过,它没有那么强大,让我们接下来看看受控组建的输入表单。

受控组件

一个受控组件接受当前的值作为参数,并且在值发生改变的时候执行回调函数。你可以说这是一种更接近的“react 方法”(这并不意味着你应该一直使用它)。

<input value={someValue} onChange={handleChange} />

这样没有问题,但是input的值必须是存在的state。通常来说,渲染成input框的组件(即表单组件)就保存在它的state中:
(当然,那也可以是另一个组件的state,甚至独立存在于状态储存中,比如说redux。)

class From extends Component {
constructor(){
super();
this.state = {
name: ''
}
}
handleNameChange = (event) => {
this.setState({name: event.target.value })
}
render(){
return (
<div>
<input
type="text"
value={this.state.name}
onChange={this.handleNameChange}
/>
</div>
);
}
}

每次你键入了一个新的字符,就会调用handleNameChange。它会获取input最新的值并在state中设置。
在React中受控和非受控的表单输入并不需要太复杂

  • 开始设置值为空字符串—''
  • 你输入一个a,然后执行handleNameChange获得a并且设置了setState,然后input输入框a被重新渲染
  • 你继续键入bhandleNameChange获得ab并且设置state,input输入框再次被重新渲染,现在的值是value=ab
     
    这种“推入式”的流程改变了表单控件,因此表单控件总是能够一直获取输入框当前的值,而不用明确知道对象是谁。

这意味着你的数据state以及UIinput总是异步的。状态将值赋給输入框,输入框通知表单改变当前的值。

这也意味着输入框发生变化时表单组件能够及时响应;例如:
- 就地反馈,例如验证
- 禁用按钮,除非所有字段都是有效数据
- 执行特定的输入格式,例如信用卡号码

但是如果你并不需要这些,认为不受控组件更简单一点,那就用不受控组件吧。

什么使元素“受控”

当然,还有其他的表单元素。你可以使用checkboxesradios以及selectstextareas
如果你通过参数来设置表单元素的值,就可以让它成为“受控组件”,就这么简单。
不过,每个表单元素都有一个不同的支持来设置该值,所以这里有一个小表来总结:

Element Value property Change callback New value in the callback
<input type="text" /> value="string" onChange event.target.value
<input type="checkbox" /> value={boolean} onChange event.target.checked
<input type="radio" /> value={boolean} onChange event.target.checked
<textarea/> value="string" onChange event.target.value
<select/> value="option value" onChange event.target.value

结论

受控和不受控表单字段都有它们的优点。评估你的具体情况并选择最合适的—对你最有效的方法就足够了。

如果你的表单在UI反馈方面极其简单,不受控的参考时完全合适的。你不需要听从许多文章说这是不好的。

feature uncontrolled controlled
一次性检索提交(例如submit
字段即时验证
有条件的禁用提交按钮
强制输入的格式
一段数据分多个输入框
动态输入