如果有讀過 React 官方文件,應該會看到這一篇文章,除了介紹表單元件有兩種(Uncontrolled 與 Controlled),還特別提到:
在大多數的情況下,我們推薦使用 controlled component 來實作表單。
如果只注重寫 code,很容易看到這就會告訴自己說:
既然官方都這樣建議了,那我就直接用 controlled component 吧!
但更進一步去想的話,如果有東西可以完勝另一個東西,那也用不著「建議」了,直接告訴我「只能」用 controlled component 就好啦~顯然這中間有些東西值得我們來看看囉!
首先肯定是要先搞懂這兩者的定義是什麼,後續的討論才有意義。由於兩者名字都太長了,容我下文直接用簡稱:
非受控元件:Uncontrolled Component
受控元件:Controlled Component
就像傳統的 HTML 表單輸入元件:
<input type="text" />
當使用者在這個 input 輸入文字,主要由 input 的 DOM 本身來儲存 value,當按下送出表單的按鈕時,會再透過抓取 DOM 節點的方式(比如事先塞一個 ref,或者 jQuery 也可以辦到),取得節點後再取得裡面存的 value。
「將 value 存在 DOM 節點內」,我們無法特別去控制它,因此叫做「非受控」。
受控元件可以參考官方文件,簡單來說,如果輸入欄位的 value property 與 onChange callback function,是由元件提供的(而不是存在 DOM 節點自己處理的),那就是受控元件,比如:
const [name, setName] = useState("Allen");
const handleNameChanged = (e) => {
setName(e.target.value);
};
return (
<input type="text" value={name} onChange={handleNameChanged} />
);
上面的例子可以看到,重點在於比起非受控元件,我們多指定了 value 與 onChange 的值給它,而這兩個背後都是由元件本身的 state 來控制,所以即便使用者從沒輸入過 Allen
這個單字,我依然可以透過 state,直接將單字塞到這個欄位上。
這邊用 state 來控制只是大多數的情況,你也可以從 props 或 context 等地方取值後塞給 value,反正只要指定了 value 與 onChange,就會是受控元件。
另外,value
只是代表這個欄位儲存的值,它不一定叫做 value
,比如 radio type 就會用 checked
:
<input type="radio" checked={false} />
非受控元件適合:
受控元件適合:
先自首一下,我就是文章開頭說的那位
既然官方都這樣建議了,那我就直接用 controlled component 吧!
當時我真的遇到所有 form 表單都用受控元件來處理,結果也真的在實務經驗上撞牆,因為我處理到了一個有幾百個欄位的 form 表單,每輸入一個字都像垂死的老人一樣,過了三秒才顯示在畫面上XD
當然我相信即便只用受控元件,依然有機會處理掉我遇到的 case,但那可能也是另一種解法了,這邊只是用自己的實務經驗,帶出「非受控元件也是很有價值的」!
且依然相信只要好好弄懂每個工具的定義、優缺點、適用情境,就能夠在正確的時候發揮出來!
controlled vs uncontrolled inputs react
這篇的分析很棒噎!!!我也是直接想都不想就都全用 controlled component 的人(跪)
實務上有個小問題想向你確認:
對於幾百個欄位的 form 表單,在送出時還是會一次抓取值並做前端的格式驗證對嗎?謝謝~
對唷!無論受控與非受控元件,submit 前的驗證都是必要的~
受控元件是比較單純,因為都是即時掌握著 state,非受控元件則可以借助 react hook form 來做到類似的效果~
好的~感謝:)