跳到主要内容

表单处理

在 React 中,表单处理通常分为“受控组件”和“非受控组件”。


在受控组件中,表单数据由 React 组件的 state 处理。

实时编辑器
function ControlledForm() {
  const [name, setName] = useState("");
  const [message, setMessage] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`提交内容 - 名字: ${name}, 留言: ${message}`);
  };

  return (
    <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
      <label>
        姓名: <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        留言: <textarea value={message} onChange={e => setMessage(e.target.value)} />
      </label>
      <button type="submit" style={{ padding: '8px', background: '#2563eb', color: 'white', border: 'none', borderRadius: '4px' }}>
        提交
      </button>
      <p style={{ color: '#666', fontSize: '14px' }}>实时预览: {name || "(未填写)"} - {message || "(未填写)"}</p>
    </form>
  );
}
结果
Loading...

2. 非受控组件 (Uncontrolled)

表单数据由 DOM 节点本身处理。使用 useRef 来从 DOM 节点中获取表单值。通常用于简单的、性能要求极高或是与第三方非 React 库集成的场景。

实时编辑器
function UncontrolledForm() {
  const inputRef = useRef(null);

  const handleSubmit = (e) => {
    e.preventDefault();
    alert(`直接从 DOM 获取的值: ${inputRef.current.value}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" ref={inputRef} placeholder="没绑定 state 的输入框" style={{ padding: '8px', borderRadius: '4px', border: '1px solid #ccc' }} />
      <button type="submit" style={{ marginLeft: '10px', padding: '8px 16px' }}>获取值</button>
    </form>
  );
}
结果
Loading...

3. 常见表单控件

复选框与单选框

实时编辑器
function SelectionDemo() {
  const [isReady, setIsReady] = useState(false);
  const [fruit, setFruit] = useState("apple");

  return (
    <div style={{ padding: '15px', border: '1px dashed #2563eb', borderRadius: '8px' }}>
      <label style={{ display: 'block', marginBottom: '10px' }}>
        <input type="checkbox" checked={isReady} onChange={e => setIsReady(e.target.checked)} />
        准备好了吗? {isReady ? "✅ 已就绪" : "❌ 未就绪"}
      </label>
      
      <label>
        选择喜欢的水果: 
        <select value={fruit} onChange={e => setFruit(e.target.value)} style={{ marginLeft: '10px', padding: '4px' }}>
          <option value="apple">🍎 苹果</option>
          <option value="banana">🍌 香蕉</option>
          <option value="orange">🍊 橙子</option>
        </select>
      </label>
      
      <div style={{ marginTop: '10px', color: '#6366f1', fontWeight: 'bold' }}>
        当前选择: {fruit}
      </div>
    </div>
  );
}
结果
Loading...

4. React 19 & Actions

React 19 引入了 Action 的概念,允许在 <form>action 属性中直接传入同步或异步函数。React 会自动处理 pending 状态。

// React 19 示例 (需 React 19 环境)
function MyForm() {
const [error, submitAction, isPending] = useActionState(async (previousState, formData) => {
const name = formData.get("name");
try {
await updateName(name);
return null;
} catch (e) {
return e.message;
}
}, null);

return (
<form action={submitAction}>
<input name="name" />
<button type="submit" disabled={isPending}>
{isPending ? "提交中..." : "提交"}
</button>
{error && <p style={{ color: 'red' }}>{error}</p>}
</form>
);
}

小结

  1. 受控组件:数据双向绑定,React 拥有绝对控制权(官方推荐)。
  2. 非受控组件:通过 ref 直接操作 DOM,减少渲染次数,适合极简场景。
  3. React 19 Actions:极大简化了异步提交逻辑,自动管理 Pending 和错误反馈。