大多数情况下,我们建议使用受控组件(也就是用React的state来控制表单元素的value值)来实现表单。在一个受控组件里,表单数据被React组件处理。另一种方案就是非控制组件,这样的话表单数据就被DOM本身所处理。
要写一个非控制组件,来替代写一个事件处理函数来处理每一次state的更新,你可以使用ref引用来从DOM里获取表单的value值。
举个例子,这段代码在一个非受控组件里接受单个属性:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
} handleSubmit(event) {
alert('A name was submitted: ' + this.input.value);
event.preventDefault();
} render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
由于一个非受控组件将数据源保留在了DOM里,那么使用非受控组件来整合React和非React代码就会更容易些。如果你想快速开发也可以写稍微少一点的代码。否则,你应该常用受控组件。
如果你还是不知道在特殊情况下你应该使用什么类型的组件,你也许看看这篇文章可以得到帮助(controlled vs uncontrolled inputs)。
默认值
在React渲染的生命周期中,表单元素中的value属性会覆盖DOM中的元素。而使用非受控组件,你经常想要让React指定初始value值,但是不再控制之后的更新。为了解决这个问题,你可以指定defaultValue属性替代value值。
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input
defaultValue="Bob"
type="text"
ref={(input) => this.input = input} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
同样,<input type="checkbox">和<input type="radio">支持dedaultChecked属性,<select>和 <textarea>支持defaultValue。
文件输入标签
在HTML中,<input type="file"> 可以让用户从其设备存储中选择一个或多个文件上传到服务器,或通过File API进行操作。
<input type="file" />
在React中,<input type="file" /> 始终是一个不受控制的组件,因为它的值只能由用户设置,而不是以编程方式设置。
您应该使用File API与文件进行交互。以下示例显示如何创建ref节点以访问提交处理程序中的文件:
class FileInput extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
alert(
`Selected file - ${this.fileInput.files[0].name}`
);
} render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Upload file:
<input
type="file"
ref={input => {
this.fileInput = input;
}} /> </label>
<br />
<button type="submit">Submit</button>
</form>
);
}
} ReactDOM.render(
<FileInput />,
document.getElementById('root')
);