表单是很常见的页面交互。React 里的“受控组件”听起来有些抽象,先从一个输入框开始:让输入框显示的值始终来自组件状态。

让状态成为数据来源

在受控输入框里,value 由 state 提供,每次输入时再通过 onChange 更新 state。这样页面显示的内容和 React 保存的值保持一致。

TSX
import { useState } from 'react'

export function NameField() {
  const [name, setName] = useState('')

  return (
    <label>
      昵称
      <input
        value={name}
        onChange={(event) => setName(event.target.value)}
      />
    </label>
  )
}

处理表单提交

表单提交时可以读取当前 state。preventDefault() 用来阻止浏览器默认刷新行为,之后再把数据交给页面自己的处理函数。

TSX
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault()
  console.log(name)
}

真实项目里,提交前还需要做必填校验,并在提交期间给用户明确反馈。

容易遇到的小问题

  • 给输入框设置了 value,却没有 onChange,输入框会变成只读。
  • 初始值可能是 undefined,之后又变成字符串。文本输入框最好从一开始就使用 ''。
  • 表单里有多个字段时,可以分别管理状态;字段更多时再考虑统一的表单方案。

小结

受控输入框把数据流讲得很清楚:state 决定当前显示值,用户输入触发事件,事件再更新 state。理解这个循环后,表单校验和提交状态也更容易组织。