React hook form(3) - useConroller & control


Posted by TempuraEngineer on 2023-03-04

目錄


control

control是useForm的回傳值,是個包了註冊component的方法的物件

不該試著存取control內的任何屬性,如果真的要說的話,它其實只能和Controller一起用


Controller

用Controller包裹組件可以讓input變成controlled component

舉例來說,像這篇提到由於MUI抽象得很深,input或者select被藏起來了,所以無法直接用register來註冊欄位,這時就會需要useController或Controller,客製化的組件也可能會用到Controller

至於為什麼input藏得很深就無法直接註冊,是因為無法直接傳遞ref給input,而react-hook-form傾向於用uncontrolled component,然後透過ref來控制DOM

在使用Controller時會需要提供以下的props

  1. name
    功能和key差不多,是一個不能重複的字串

  2. render
    一個回傳你要註冊的controlled component的function
    react-hook-form會幫你把controlled component整合進去,因此就能使用field、fieldState、formState了

  3. defaultValue
    如果會用到reset的話,那要提供dedefaultValue,且注意絕對不要提供undefined

const { handleSubmit, control } = useForm({ 
   ReactSelect: { value: "vanilla", label: "Vanilla" },
});

return (
   <form onSubmit={handleSubmit((data) => console.log(data))}>
       <Controller
          name="ReactSelect"
          control={control}
          render={({ field }) => (
             <ReactSelect
                  isClearable
                  {...field}
                  options={[
                     { value: "apple", label: "Apple" },
                     { value: "strawberry", label: "Strawberry" },
                     { value: "banana", label: "Banana" }
                  ]}
              />
          )}
       />
   </form>
);


useController

和Controller+control一樣用於有controlled component的場景

接收name、control、defaultValues、rule...等,其中control是來自useForm回傳,通常只在用到FormProvider的場景使用,rule則是用於驗證

並回傳以下幾個東西field、formState、fieldState,field類似於useForm回傳的register,

field.ref則用於連結controlled component和react-hook-form,當handleSubmit觸發時,會進行驗證,然後focus有error的input

至於formState和fieldState與useForm差不多

const {
    field,
    fieldState: { invalid, isTouched, isDirty },
    formState: { touchedFields, dirtyFields }
  } = useController({
    name: 'Name',
    control,
    rules: { required: true },
  });

return (
    <>
        <TextField 
          onChange={field.onChange}
          onBlur={field.onBlur}
          value={field.value}
          name={field.name} // 欄位名,不可重複
          inputRef={field.ref} // ref是用於連結react-hook-form和這個input
        />

        {/ * 等同於上段 * /}
        <TextField 
           {...field}
        />
    </>
  );


參考資料

react-hook-form - control
react-hook-form - useController


#react-hook-form #useController #control #controller #controlled component







Related Posts

[ Day 01 ] Python unittest 單元測試 | 專案應用分享

[ Day 01 ] Python unittest 單元測試 | 專案應用分享

學習 Git (3) - 開始版控的最後一步:Commit

學習 Git (3) - 開始版控的最後一步:Commit

Java 學習筆記 06 – 類別與物件 Part 1(名詞介紹)

Java 學習筆記 06 – 類別與物件 Part 1(名詞介紹)


Comments