🎙 歡迎來到《前端達人 · 播客書單》第 23 期。
視頻版(播客風格更精彩)
今天我們聚焦一個「寫前端永遠逃不掉」的主題:表單處理。 你有沒有遇到過這些問題:
表單怎么一改就卡?state 是不是用錯了?
有時候 value 控不住輸入框,直接報錯?
面試被問“受控和非受控的區別”,說不清楚?
別急,這一期我們就用真實例子 + 背后原理,一次性理清楚 React 中的表單處理邏輯,帶你站在更工程化的視角看表單。
一、問題導入:React 的表單處理,為什么需要重新發明輪子?
在原生 HTML 中,表單元素(比如?<input>
)自帶內部狀態:
你填了什么,瀏覽器記著;你點了提交,瀏覽器打包給后端。
但到了 React,“組件狀態要統一由你來掌控”,這就帶來一個問題:
🔄 要不要把?
<input>
?的值也交給組件 state 管?
這時候你就面臨選擇:
做法 | 特點 |
---|---|
受控組件 | React 負責存 & 改值,value 受 state 控制 |
非受控組件 | 瀏覽器 DOM 自己管理,React 只負責“拿一下” |
很多初學者會覺得“我只是個輸入框,哪來那么復雜”,但其實——寫 React 表單沒寫好,是最容易留下 bug 的地方之一。
二、核心定義:什么是受控字段、非受控字段?
📌?受控字段 Controlled Field
React 完全掌控字段值,配合?value
?+?onChange
?實現數據同步。
每次用戶輸入,觸發?
onChange
?→ 調用?setState
?更新值。下次 render 時,
value={state}
?將新值綁定回組件。
📌?非受控字段 Uncontrolled Field
React 不管輸入框的值,用瀏覽器默認行為,必要時通過?ref
?獲取 DOM 節點來拿值。
初始化用?
defaultValue
獲取用?
ref.current.value
🧠 一句話總結:
Controlled 是“值存我這”,Uncontrolled 是“值你自己管”。
三、使用方式與典型代碼
? 受控組件代碼:
const?[name, setName] = useState('');<inputtype="text"value={name}onChange={e?=>?setName(e.target.value)}
/>
🔍 解釋:
value={name}
:值由組件狀態決定onChange
:每次輸入更新組件 stateReact 全程控制這個 input,數據同步準確、可控性強
? 非受控組件代碼:
const?nameRef = useRef();<input?type="text"?defaultValue="Tom"?ref={nameRef}?/><button?onClick={()?=>?alert(nameRef.current.value)}>提交
</button>
🔍 解釋:
用?
defaultValue
?初始化值,只作用于第一次渲染后續輸入的值保存在 DOM 中
提交按鈕用?
ref.current.value
?獲取當前值
四、工作機制:受控與非受控的背后原理
Controlled 的思路:React 的“統一狀態來源”原則
在 React 中,組件的 UI = 函數(state) 所以任何用戶行為,最終都應該反映到 state 上,形成閉環:
State → Render UI → onChange Event → Update State
🔁 每次輸入其實是兩次操作:
用戶輸入觸發?
onChange
我們手動用?
setState
?改值,再 render 回去
雖然多了一步,但換來了:
??狀態統一管理
??更容易 debug 和回溯
??便于聯動邏輯(如禁用按鈕、動態校驗)
Uncontrolled 的思路:用瀏覽器原生行為節省性能
它就像「只讀收件箱」:
你不監聽每一個字怎么輸入
你只關心“用戶最終輸入了什么”
適用于這種場景:
你只在點擊「提交」時需要值
不需要做任何即時 UI 反饋
五、典型應用場景分析
場景 | 推薦寫法 | 理由 |
---|---|---|
用戶注冊、登錄 | Controlled | 需要實時反饋和驗證 |
文件上傳 | Uncontrolled | <input type="file"> ?是只讀字段 |
表單僅用于一次性收集值 | Uncontrolled | 節省性能 |
表單字段需要與其他組件狀態聯動 | Controlled | 更可維護 |
使用 React Hook Form | Controlled + ref混合 | 更高效的封裝形式 |
💡 文件上傳字段是一個經典案例:
<input type="file"?ref={fileRef} />
為什么不能用受控寫法? 因為?<input type="file">
?的?value
?是只讀的!
六、易錯點提示 ??
? 新手常見誤區:
<input value="abc"?/>
不綁定?onChange
?就寫?value
,React 會警告你:你讓它受控了,但不給它機會改變!
? 正確做法:
const?[value, setValue] = useState('abc');
<input?value={value}?onChange={e?=>?setValue(e.target.value)} />
? 常見對比總結:
項目 | 受控字段 | 非受控字段 |
---|---|---|
控制權 | React state | DOM 自身 |
使用場景 | 表單聯動、即時校驗 | 簡單提交、上傳文件 |
性能 | 會觸發重新渲染 | 不依賴組件更新 |
調試性 | 更容易統一 debug | 值存 DOM,調試成本高 |
七、總結復盤 🧠
🎯 受控字段:優先使用,適合一切中大型表單
?? 非受控字段:在“只讀、輕量、特殊場景”中可以使用
🔄 Controlled 代表 React 哲學,Uncontrolled 保留 HTML 本能
🚧 避免 value 無 onChange;避免 file 字段用 state 控制
🔁 兩者可以混合使用,尤其在大型表單組件中(如 React Hook Form)
🎯 下期預告
下一期,我們將上手使用社區最火的表單庫之一 ——?React Hook Form,帶你感受表單處理的極致簡潔。
#React? ?#React播客??#前端播客??#前端達人??#TypeScript?