昨天討論到 Uncontrolled Component 與 Controlled Component,了解到非受控元件因為是用原生的 HTML 輸入 tag,因此可以做到較佳的 render 效率,但相對的,因為即時取得非受控元件的值是困難的,所以較難做到複雜的 UI 交互行為。
那,有沒有可能有一個工具,可以同時兼有這兩者的優點呢(少 render & 方便取值)?我們今天來討論 React Hook Form。
由於 React 官網已經說白了,官方更推薦我們使用 Controlled Component,我想主因可能是希望讓 state 成為表單欄位值的唯一來源,透過 React 元件統一控管,且一些像是 MUI 的 UI library,與 Controlled Component 的相容性是較佳的。
但就如同昨天的討論,使用 Controlled Component 就必須面對容易頻繁 re-render 的問題,如果要寫一個欄位數量龐大的 form 表單,就會遇到 render 效率的問題。
另外,因為每一個欄位都要一組 state 來控制,就會需要寫相當多非常類似的 state 與 useState,也是一個滿費工的過程。
React Hook Form 是一個專門針對 React functional component 設計的,用來更好管理 form 表單的 library。
Performant, flexible and extensible forms with easy-to-use validation.
標榜一些強力的 feature:
而能夠做到上述一系列跟「效能」息息相關的操作,都歸功於 React Hook Form 是一個以 Uncontrolled Component 為主的 library,可以參考官網說法,透過 ref 屬性,讓 React Hook Form 能繞過 React 的 Virtual DOM,訪問輸入元件真實的 DOM nodes。
雖然以 Uncontrolled Component 為主,但面對要串接 MUI 這樣的 UI library,偶爾還是需要在 form 表單內放幾個 Controlled Component,這時也可以透過內建的 Controller
或 useController
,用來限制 re-render 的 scope,一樣做到「誰更新就自己 re-render 就好」。
useForm
即可,不需額外 import component
其實如果應用程式中常常需要讓使用者填寫表單,就會經常遇到各種表單的控管問題,比如狀態管理、檢核(validation)、表單狀態(isDirty、submitting)等,這時通常會從像是 Redux Form(但它的作者推薦使用 React Final Form)、React Hook Form、Formik 等熱門選項挑一個來使用,它們都實作了表單管理的基本需求。
而 React Hook Form 自己最主打的就是「透過 Uncontrolled Component 來提高 performance,減少 re-render」,因此如果經常需要處理大量欄位的表單,我想 React Hook Form 會是很不錯的選擇。
其實我最早是使用 Redux Form 在處理表單需求,Redux Form 雖然方便直覺,但因為剛好公司產品經常會用大量欄位且複雜互動的表單,這種表單往往打一個字母就要 lag 三秒鐘,很容易讓使用者崩潰,因此公司內部還決定試試看 React Hook Form。
中間雖然要轉換 Controlled 到 Uncontrolled 的思維,其實還是花了不少心力去適應,不過確實是順利解決了 performance issue,而且有了這個經驗,未來轉換的路會更加輕鬆!