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>
  )
}

什么时候用非受控组件

  1. 简单表单,不需要实时验证
  2. 文件上传(<input type="file"> 必须非受控)
  3. 集成非 React 代码
  4. 大型表单性能优化
// 文件上传必须非受控
const fileRef = useRef()
<input type="file" ref={fileRef} />

推荐做法

同分类其他题目