<input value={text} onChange={e =>"> <input value={text} onChange={e =>"> <input value={text} onChange={e =>">
React 词条目录
前端Wiki/React/进阶/表单实战

受控组件

受控组件 = 表单元素的值由 state 控制:<input value={text} onChange={e => setText(e.target.value)} />。数据从 state 流向输入框,用户输入再经 onChange 流回 state——整个回路里 React 是唯一数据源。

与“非受控”(直接读 DOM,如 defaultValue + ref)相比,受控组件可以做即时校验、禁用提交、格式化输入。除非简单一次性表单(如搜索框),都推荐受控写法。

  • 受控 = value 绑定 state + onChange 写回 state,数据单向闭环
  • textarea、select 同理:value + onChange,没有 v-model 语法糖
  • 即时校验、按钮禁用、格式化输入都基于受控实现
HTML
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>受控组件</title>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState } = React;

function Form() {
  const [name, setName] = useState('');
  const [intro, setIntro] = useState('');
  const [city, setCity] = useState('北京');

  // 即时校验:基于 state 直接算
  const tooShort = name.length > 0 && name.length < 2;

  function submit(e) {
    e.preventDefault();
    alert('提交:' + name + ' / ' + city + ' / ' + intro);
  }

  return (
    <form onSubmit={submit} style={{ padding: 16 }}>
      <p>
        姓名:<input value={name} onChange={e => setName(e.target.value)} />
        {tooShort && <span style={{ color: 'red' }}> 太短了(不少于 2 字)</span>}
      </p>
      <p>
        简介:<textarea value={intro} onChange={e => setIntro(e.target.value)} />
      </p>
      <p>
        城市:
        <select value={city} onChange={e => setCity(e.target.value)}>
          <option>北京</option><option>上海</option><option>深圳</option>
        </select>
      </p>
      <button type="submit" disabled={tooShort || !name}>提交</button>
    </form>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Form />);
</script>
</body>
</html>
本节要点受控组件 = value 绑 state + onChange 回写 state;校验、禁用、格式化都因此简单。
🔗 相关词条JavaScriptHTMLVue