React
用 value 和 onChange 显式实现受控表单。
在线预览
实时 state
小明
正在学习:React
已保存:0 次
组件关系与数据流
Form StateComponentBindingDOM Control
差异焦点读取、更新和回写都是显式代码,state 是唯一数据源。
实线表示依赖、数据或命令传递,虚线表示事件、回调或清理路径。
flowchart TB
accTitle: React 受控表单数据流
accDescr: input 事件读取 DOM value,onChange 调用 setter 更新 state,组件重新渲染后再通过 value prop 把状态写回表单控件。
input[("input / select DOM")] -.->|"onChange event"| handler{{"读取 event.target.value"}}
handler --> setter{{"调用 setter"}}
setter --> state(["name / direction state"])
state --> demo["ReactDemo render"]
demo -->|"value prop"| input
class state state
class demo component
class handler,setter process
class input resource
classDef state fill:#ffffff,stroke:#149eca,color:#172033,stroke-width:1.2px
classDef component fill:#e5f6fb,stroke:#149eca,color:#172033,stroke-width:2px,font-weight:600
classDef process fill:#f4fbfd,stroke:#149eca,color:#172033,stroke-width:1.6px
classDef resource fill:#f3f5f8,stroke:#778195,color:#172033,stroke-width:1.4px事件把 DOM 值提交给 state,下一次 render 再用 value prop 控制表单。
实际运行源码
import { useState } from "react";import type { FormEvent } from "react";
export function ReactDemo() { const [name, setName] = useState("小明"); const [direction, setDirection] = useState("React"); const [submitted, setSubmitted] = useState(0);
function submit(event: FormEvent<HTMLFormElement>) { event.preventDefault(); setSubmitted((current) => current + 1); }
return ( <div className="demo-stack"> <form className="demo-form" onSubmit={submit}> <label className="demo-field"> 姓名 <input className="demo-input" value={name} onChange={(event) => setName(event.target.value)} /> </label> <label className="demo-field"> 学习方向 <select className="demo-select" value={direction} onChange={(event) => setDirection(event.target.value)} > <option>React</option> <option>Vue</option> <option>两者对比</option> </select> </label> <button className="demo-button" type="submit"> 保存资料 </button> </form> <div className="demo-card"> <span className="demo-tag">实时 state</span> <h2>{name || "未填写姓名"}</h2> <p>正在学习:{direction}</p> <p>已保存:{submitted} 次</p> </div> </div> );}