受控组件
受控组件(Controlled Components)是 React 中处理表单输入的一种方式。在受控组件中,表单元素的值由 React 的状态管理,并通过 value 属性传递给这些元素。每当用户输入内容时,都会触发一个事件处理器来更新状态,从而保持同步。这种方式使得你可以完全控制表单的状态和行为,包括验证、格式化和展示。
受控组件的基本概念
- 状态(State):使用
useState或其他状态管理机制来保存表单字段的值。 - 事件处理器(Event Handlers):监听用户的输入事件(如
onChange),并在事件发生时更新状态。 - 同步(Synchronization):通过将状态绑定到表单元素的
value属性上,确保表单元素始终反映最新的状态。
示例:文本输入框
以下是一个简单的例子,展示了如何创建一个受控的文本输入框:
import React, { useState } from "react";
function NameForm() {
const [name, setName] = useState("");
function handleChange(event) {
setName(event.target.value);
}
function handleSubmit(event) {
alert("A name was submitted: " + name);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default NameForm;在这个例子中,NameForm 组件使用 useState 来跟踪输入框的值,并通过 onChange 事件处理器更新这个状态。当用户提交表单时,会弹出一个警告框显示输入的名字。
处理多个输入
对于包含多个输入字段的表单,你可以将每个字段的状态存储在一个对象中,并根据 name 属性来区分不同的输入:
import React, { useState } from "react";
function FormWithMultipleInputs() {
const [formData, setFormData] = useState({
username: "",
email: "",
});
function handleChange(event) {
const { name, value } = event.target;
setFormData((prevState) => ({
...prevState,
[name]: value,
}));
}
function handleSubmit(event) {
alert(`Username: ${formData.username}, Email: ${formData.email}`);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Username:
<input
name="username"
type="text"
value={formData.username}
onChange={handleChange}
/>
</label>
</div>
<div>
<label>
Email:
<input
name="email"
type="email"
value={formData.email}
onChange={handleChange}
/>
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default FormWithMultipleInputs;受控选择框(Select Box)
处理 <select> 元素与处理文本输入类似,但需要注意的是你需要为每个选项设置 value 属性,并且在状态中保存所选选项的值。
import React, { useState } from "react";
function FlavorForm() {
const [flavor, setFlavor] = useState("coconut");
function handleChange(event) {
setFlavor(event.target.value);
}
function handleSubmit(event) {
alert("Your favorite flavor is: " + flavor);
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<label>
Pick your favorite La Croix flavor:
<select value={flavor} onChange={handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
export default FlavorForm;受控复选框(Checkbox)
处理复选框稍微有些不同,因为它们有 checked 而不是 value 属性。你需要用布尔值来表示是否选中。
import React, { useState } from "react";
function ToggleButton() {
const [isToggled, setIsToggled] = useState(false);
function handleChange(event) {
setIsToggled(event.target.checked);
}
return (
<label>
Toggle me
<input type="checkbox" checked={isToggled} onChange={handleChange} />
</label>
);
}
export default ToggleButton;文件上传
处理文件上传时,你可以使用 <input type="file" /> 元素,并结合受控或非受控的方式读取文件信息。
示例:受控文件上传
import React, { useState } from "react";
function FileUpload() {
const [selectedFile, setSelectedFile] = useState(null);
function handleFileChange(event) {
setSelectedFile(event.target.files[0]);
}
function handleSubmit(event) {
if (selectedFile) {
console.log(selectedFile);
}
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Upload file:
<input type="file" onChange={handleFileChange} />
</label>
</div>
<button type="submit">Submit</button>
</form>
);
}
export default FileUpload;表单验证
React 不提供内置的表单验证机制,但你可以很容易地实现自己的验证逻辑。通常的做法是在提交表单前检查各个字段的有效性,并根据需要显示错误消息。
示例:简单验证
import React, { useState } from "react";
function ValidatedForm() {
const [email, setEmail] = useState("");
const [error, setError] = useState("");
function validateEmail(email) {
// 简单的正则表达式验证
const re = /\S+@\S+\.\S+/;
return re.test(String(email).toLowerCase());
}
function handleChange(event) {
setEmail(event.target.value);
}
function handleSubmit(event) {
if (!validateEmail(email)) {
setError("Invalid email address");
} else {
setError("");
alert("Valid email address!");
}
event.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Email:
<input type="email" value={email} onChange={handleChange} />
</label>
</div>
{error && <p style={{ color: "red" }}>{error}</p>}
<button type="submit">Submit</button>
</form>
);
}
export default ValidatedForm;使用 Hook 和自定义逻辑
随着 React 的发展,越来越多的功能可以通过 Hooks 实现。例如,你可以创建自定义 Hook 来封装表单逻辑,或者使用第三方库如 Formik 或 react-hook-form 来简化复杂的表单处理。
示例:使用 react-hook-form
react-hook-form 是一个流行的库,它提供了非常轻量级的 API 来处理表单,同时支持验证、异步验证等功能。
首先安装库:
npm install react-hook-form然后使用它来构建表单:
import React from "react";
import { useForm } from "react-hook-form";
function HookFormExample() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm();
function onSubmit(data) {
console.log(data);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>First Name</label>
<input {...register("firstName", { required: true })} />
{errors.firstName && <p>First Name is required</p>}
</div>
<div>
<label>Last Name</label>
<input {...register("lastName")} />
</div>
<input type="submit" />
</form>
);
}
export default HookFormExample;在这个例子中,我们使用了 react-hook-form 提供的 useForm Hook 来注册表单字段,并在提交时获取它们的值。此外,还可以轻松地添加验证规则并在必要时显示错误消息。
总结
受控组件是 React 中一种强大且灵活的方式来管理表单数据和用户输入。通过将表单元素的状态与 React 的状态同步,你可以获得对表单的全面控制,包括实时验证、格式化和响应用户交互。