人子來,不是要受人的服事,乃是要服事人。(馬太福音 廿:28)
React Hook Form - 06 - useWatch
ArticleImage
useWatchReact Hook Form 提供的一個自訂 Hook,作用類似於 watch API,但有一些不同的特性,使用 useWatch 可以讓你在監控表單欄位值的同時,避免全表單或應用程式的重新渲染,從而有可能提升效能。 接下來,我們會一起學習如何使用 useWatch 的功能。

useWatch 的功能和 watch 非常相似,都是用來監控表單欄位的變化,並回傳欄位的最新值,不過,useWatch 會限制在自訂 hook 的層級進行重新渲染,而不會像 watch 那樣觸發整個表單或應用程式的重新渲染,這樣能有更好的效能。

[ TypeScript ]
useWatch: ({ control?: Control, name?: string, defaultValue?: unknown, disabled?: boolean }) => object

指定要監控的 `欄位名稱`,如果是單一欄位,可以直接傳入欄位名稱(如 'username'),如果需要監控多個欄位,則可以傳入一個字串陣列(如 ['username', 'email'])。

[ TypeScript ]
name?: string | string[] | undefined;

範例: 

[ TypeScript ]
// 監控單一欄位 const username = useWatch({ name: 'username' }); // 監控多個欄位 const [username, email] = useWatch({ name: ['username', 'email'] });

這是 useFormcontrol 物件,通常由 useForm 回傳控制的物件,若你使用的是 FormProvider,則這個參數是可選的。

[ TypeScript ]
control?: Control;
範例:
[ TypeScript ]
// 使用 useForm 返回的 control const { control } = useForm(); const username = useWatch({ control, name: 'username' });

設置 useWatch 在第一次渲染時回傳的預設值,這個值會在首次渲染時顯示出來,直到欄位的值被更新為止,如果提供 defaultValue,則第一次渲染時會使用該預設值。

[ TypeScript ]
defaultValue?: unknown;
範例:
[ TypeScript ]
// 若 `username` 沒有被修改,則會顯示 'guest' const username = useWatch({ name: 'username', defaultValue: 'guest' });

設置是否禁用欄位的訂閱,如果設置為 true,則不會訂閱該欄位的變化。

[ TypeScript ]
disabled?: boolean = false;

範例: 

[ TypeScript ]
// 這樣設置會讓 `username` 不再訂閱並不會觸發重新渲染 const username = useWatch({ name: 'username', disabled: true });

這個屬性會啟用精確匹配的欄位名稱訂閱,如果設置為 true,只有當欄位名稱完全匹配時才會觸發變更,這對於有複雜名稱結構的情況非常有用。

[ TypeScript ]
exact?: boolean = false;
範例:
[ TypeScript ]
// 只有當 'user.name' 欄位變更時才會觸發重新渲染 const username = useWatch({ name: 'user.name', exact: true });
  • 效能優化:當表單中有多個欄位,且你只需要監控某些特定欄位的變化時,使用 useWatch 可以避免不必要的整體重新渲染。

  • 表單結構複雜:如果你的表單結構較為複雜,且某些欄位不需要觸發整體表單的重新渲染時,useWatch 可以幫助你更精確地控制需要重新渲染的欄位。

[ TypeScript ]
import React from 'react'; import { useForm, Controller, useWatch } from 'react-hook-form'; function MyForm() { const { control, handleSubmit } = useForm(); // 使用 useWatch 來監控 username 欄位 const username = useWatch({ control, name: 'username', defaultValue: '' }); const onSubmit = (data) => { console.log(data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="username" control={control} render={({ field }) => <input {...field} />} /> <p>監控的 username 值: {username}</p> <button type="submit">Submit</button> </form> ); }

在這個範例中,useWatch 用來監控 username 欄位的值,並將其顯示在頁面上,每當 username 的值變更時,useWatch 會觸發該欄位的重新渲染。

總結:

  • useWatch 與 watch 類似,但它的優勢在於能夠限制重新渲染的範圍,只針對監控的欄位進行渲染,而不會影響整個表單或應用的效能。

  • 你可以使用 namecontroldefaultValue 等屬性來設置監控的欄位、提供預設值等,從而精細控制哪些欄位的變化需要觸發重新渲染。

  • 當需要對表單中的某些欄位進行性能優化或只關心特定欄位的變化時,useWatch 是一個非常有用的工具。