标准答案
- 受控组件把 value、checked 等值绑定到 React state,并通过 onChange 更新 state。
- 非受控组件不把每次输入都同步到 React state,表单值由 DOM 自己维护,需要时通过 ref 或 FormData 读取。
- 受控组件适合实时校验、联动、格式化、禁用提交、跨字段依赖和需要状态可预测的场景。
- 非受控组件适合简单表单、文件上传、大量输入项或不需要实时响应每次输入的场景。
- 二者不是绝对对立。实际项目可以让关键字段受控,低价值字段非受控,或者使用表单库管理订阅粒度。
题目解析
这道题要围绕“数据源在哪里”回答:受控的数据源在 React,非受控的数据源在 DOM。
受控组件可预测性更强,但每次输入都可能触发 React 更新;非受控性能和接入简单,但联动和校验能力弱。
文件 input 通常是非受控的,因为浏览器不允许用 value 直接控制文件选择。
代码示例
下面展示受控输入和非受控读取。
TSX
function ControlledInput() {
const [keyword, setKeyword] = useState('')
return (
<input
value={keyword}
onChange={event => setKeyword(event.target.value)}
/>
)
}TSX
function UncontrolledInput() {
const inputRef = useRef<HTMLInputElement>(null)
function submit() {
console.log(inputRef.current?.value)
}
return <input ref={inputRef} defaultValue="" />
}常见误区
- 同时给 input 写 value 和 defaultValue,混淆受控和非受控模式。
- 受控组件没有 onChange,导致输入框无法正常编辑。
- 复杂联动表单完全非受控,后续校验、回填和提交态难以管理。