1. 受控component
in Reactin, 受控component is 指由Reactstatus控制其值 表单元素. 当user输入时, 表单元素 值会updateReactstatus, 而Reactstatus又控制着表单元素 显示值.
function ControlledForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prevState => ({
...prevState,
[name]: value
}));
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('表单data:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">姓名: </label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="email">邮箱: </label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label htmlFor="password">password: </label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</div>
<button type="submit">submitting</button>
</form>
);
}
提示
受控component 优点 is 表单data完全由Reactstatus控制, 便于implementation表单verification and 实时反馈.
2. 非受控component
非受控component is 指由DOM本身控制其值 表单元素, React不直接控制其值, 而 is throughref来访问DOM元素 值.
function UncontrolledForm() {
const nameRef = useRef(null);
const emailRef = useRef(null);
const passwordRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
const formData = {
name: nameRef.current.value,
email: emailRef.current.value,
password: passwordRef.current.value
};
console.log('表单data:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">姓名: </label>
<input type="text" id="name" ref={nameRef} />
</div>
<div>
<label htmlFor="email">邮箱: </label>
<input type="email" id="email" ref={emailRef} />
</div>
<div>
<label htmlFor="password">password: </label>
<input type="password" id="password" ref={passwordRef} />
</div>
<button type="submit">submitting</button>
</form>
);
}
warning
非受控component using场景较 few , 一般只 in 需要直接operationDOM or migration现 has code时using.
3. 表单verification
表单verification is 确保user输入data符合要求 important 步骤. Reactin可以throughstatusmanagement and 条件渲染implementation表单verification.
function ValidatedForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({});
const validate = () => {
const newErrors = {};
if (!formData.name.trim()) {
newErrors.name = '姓名不能 for 空';
}
if (!formData.email.trim()) {
newErrors.email = '邮箱不能 for 空';
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = '邮箱格式不正确';
}
if (!formData.password) {
newErrors.password = 'password不能 for 空';
} else if (formData.password.length < 6) {
newErrors.password = 'password long 度不能 few 于6位';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prevState => ({
...prevState,
[name]: value
}));
// 实时清除 for 应字段 errorinformation
if (errors[name]) {
setErrors(prevErrors => {
const newErrors = { ...prevErrors };
delete newErrors[name];
return newErrors;
});
}
};
const handleSubmit = (e) => {
e.preventDefault();
if (validate()) {
console.log('表单data:', formData);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">姓名: </label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
className={errors.name ? 'error' : ''}
/>
{errors.name && <p className="error-message">{errors.name}</p>}
</div>
<div>
<label htmlFor="email">邮箱: </label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
className={errors.email ? 'error' : ''}
/>
{errors.email && <p className="error-message">{errors.email}</p>}
</div>
<div>
<label htmlFor="password">password: </label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
className={errors.password ? 'error' : ''}
/>
{errors.password && <p className="error-message">{errors.password}</p>}
</div>
<button type="submit">submitting</button>
</form>
);
}
4. 表单submittingprocessing
表单submitting时, 通常需要processingdata发送 to server 逻辑. in Reactin, 可以usingasync/await or Promise来processingasynchronousrequest.
function SubmitForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitSuccess, setSubmitSuccess] = useState(false);
// verificationfunction...
const handleSubmit = async (e) => {
e.preventDefault();
if (validate()) {
setIsSubmitting(true);
try {
const response = await fetch('https://api.example.com/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
if (response.ok) {
const data = await response.json();
console.log('register成功:', data);
setSubmitSuccess(true);
// reset表单
setFormData({ name: '', email: '', password: '' });
} else {
const errorData = await response.json();
setErrors({
submit: errorData.message || 'register失败, 请稍 after 重试'
});
}
} catch (error) {
setErrors({
submit: 'networkerror, 请稍 after 重试'
});
} finally {
setIsSubmitting(false);
}
}
};
return (
<div>
{submitSuccess && <p className="success-message">register成功!</p>}
<form onSubmit={handleSubmit}>
{/* 表单字段... */}
{errors.submit && <p className="error-message">{errors.submit}</p>}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'submittingin...' : 'submitting'}
</button>
</form>
</div>
);
}
5. complex 表单processing
for 于package含复选框, 单选按钮, under 拉菜单etc. complex 表单, 可以usingclass似 方式processing.
function ComplexForm() {
const [formData, setFormData] = useState({
gender: 'male',
hobbies: [],
city: '',
agree: false
});
const handleGenderChange = (e) => {
setFormData(prevState => ({
...prevState,
gender: e.target.value
}));
};
const handleHobbyChange = (e) => {
const { value, checked } = e.target;
setFormData(prevState => {
if (checked) {
return {
...prevState,
hobbies: [...prevState.hobbies, value]
};
} else {
return {
...prevState,
hobbies: prevState.hobbies.filter(hobby => hobby !== value)
};
}
});
};
const handleCityChange = (e) => {
setFormData(prevState => ({
...prevState,
city: e.target.value
}));
};
const handleAgreeChange = (e) => {
setFormData(prevState => ({
...prevState,
agree: e.target.checked
}));
};
const handleSubmit = (e) => {
e.preventDefault();
console.log('表单data:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>性别: </label>
<div>
<input
type="radio"
id="male"
name="gender"
value="male"
checked={formData.gender === 'male'}
onChange={handleGenderChange}
/>
<label htmlFor="male">男</label>
<input
type="radio"
id="female"
name="gender"
value="female"
checked={formData.gender === 'female'}
onChange={handleGenderChange}
/>
<label htmlFor="female">女</label>
</div>
</div>
<div>
<label>爱 good : </label>
<div>
<input
type="checkbox"
id="reading"
name="hobbies"
value="reading"
checked={formData.hobbies.includes('reading')}
onChange={handleHobbyChange}
/>
<label htmlFor="reading">阅读</label>
<input
type="checkbox"
id="sports"
name="hobbies"
value="sports"
checked={formData.hobbies.includes('sports')}
onChange={handleHobbyChange}
/>
<label htmlFor="sports">运动</label>
<input
type="checkbox"
id="music"
name="hobbies"
value="music"
checked={formData.hobbies.includes('music')}
onChange={handleHobbyChange}
/>
<label htmlFor="music">音乐</label>
</div>
</div>
<div>
<label htmlFor="city">城市: </label>
<select
id="city"
name="city"
value={formData.city}
onChange={handleCityChange}
>
<option value="">请选择城市</option>
<option value="beijing">北京</option>
<option value="shanghai"> on 海</option>
<option value="guangzhou">广州</option>
<option value="shenzhen">深圳</option>
</select>
</div>
<div>
<input
type="checkbox"
id="agree"
name="agree"
checked={formData.agree}
onChange={handleAgreeChange}
/>
<label htmlFor="agree">我同意条款 and 条件</label>
</div>
<button type="submit">submitting</button>
</form>
);
}
6. using第三方libraryprocessing表单
for 于 complex 表单, 还可以using第三方librarysuch asFormik, React Hook Formetc.来简化表单processing.
// usingReact Hook Formexample
import { useForm } from 'react-hook-form';
function HookForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log('表单data:', data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label htmlFor="name">姓名: </label>
<input
type="text"
id="name"
{...register('name', { required: '姓名不能 for 空' })}
/>
{errors.name && <p className="error-message">{errors.name.message}</p>}
</div>
<div>
<label htmlFor="email">邮箱: </label>
<input
type="email"
id="email"
{...register('email', {
required: '邮箱不能 for 空',
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: '邮箱格式不正确'
}
})}
/>
{errors.email && <p className="error-message">{errors.email.message}</p>}
</div>
<button type="submit">submitting</button>
</form>
);
}
练习 1: creation受控表单
- creation一个package含姓名, 邮箱, 电话 受控表单
- implementation实时表单verification
- 添加submitting按钮, 点击时显示表单data
练习 2: processing complex 表单
- creation一个package含单选按钮, 复选框, under 拉菜单 complex 表单
- implementation表单verification
- 添加submitting按钮, 点击时显示表单data