React 中受控组件和非受控组件的区别?
受控组件
表单数据由 React state 管理,每次输入都更新 state。
function ControlledForm() {
const [value, setValue] = useState('')
return (
<input
value={value}
onChange={e => setValue(e.target.value)}
/>
)
}非受控组件
表单数据由 DOM 自己管理,React 通过 ref 获取值。
function UncontrolledForm() {
const inputRef = useRef()
const handleSubmit = () => {
console.log(inputRef.current.value)
}
return (
<>
<input ref={inputRef} defaultValue="initial" />
<button onClick={handleSubmit}>Submit</button>
</>
)
}对比
| 特性 | 受控组件 | 非受控组件 |
|---|---|---|
| 数据源 | React state | DOM |
| 值获取 | state 变量 | ref.current.value |
| 实时验证 | ✅ 每次 onChange | ❌ 需手动获取 |
| 默认值 | value 属性 | defaultValue |
| 性能 | 每次输入触发渲染 | 不触发渲染 |
| 推荐度 | ⭐⭐⭐ | ⭐ |
受控组件示例
function Form() {
const [form, setForm] = useState({
username: '',
email: '',
role: 'user'
})
const handleChange = (e) => {
setForm(prev => ({
...prev,
[e.target.name]: e.target.value
}))
}
return (
<form>
<input name="username" value={form.username} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
<select name="role" value={form.role} onChange={handleChange}>
<option value="user">User</option>
<option value="admin">Admin</option>
</select>
</form>
)
}什么时候用非受控组件
- 简单表单,不需要实时验证
- 文件上传(
<input type="file">必须非受控) - 集成非 React 代码
- 大型表单性能优化
// 文件上传必须非受控
const fileRef = useRef()
<input type="file" ref={fileRef} />推荐做法
- 默认使用受控组件(数据流清晰)
- 简单场景或性能敏感时用非受控组件
- 大型表单考虑使用 React Hook Form 等库(底层是非受控 + 按需更新)