iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0
自我挑戰組

請問這是魔法嗎?前端轉職菜雞的修煉之路!系列 第 10

DAY 10 招喚表單魔法陣 - React Hook Form (3) 此受控非彼獸控的表單套件組合技 Controller

  • 分享至 

  • xImage
  •  

今天來說說如何將 React Hook Form 與其他 UI 框架結合使用~

昨天的範例是使用原生的表單標籤,但實際開發上,還是會傾向使用 UI 框架提供的表單元件,那如何當個兩個都要的成熟大人呢?要知道這個問題的答案,首先我們先知道什麼是受控元件和非受控元件:

  1. 非受控元件
    這種元件的值不受 React state 控制,是由 DOM 自己管理,React 不會持續追蹤它,需要取值的話,可使用ref.current.value拿取值。
function UncontrolledExample() {
  return (
    <form>
      {/* React 沒有 value state,input 自己管理 */}
      <input type="text" defaultValue="預設值" />
    </form>
  )
}
  1. 受控元件
    這種元件的值就是受 React state 控制,input 的 value 必須綁定 state。改變值只能透過 setState。
import { useState } from "react"

function ControlledExample() {
  const [value, setValue] = useState("")

  return (
    <form>
      <input
        type="text"
        value={value} // 受 React state 控制
        onChange={(e) => setValue(e.target.value)}
      />
      <p>目前輸入:{value}</p>
    </form>
  )
}

所以我們必須先了解我們使用的 UI 框架的元件是屬於受控還是非受控元件,若是非受控元件,我們就能直接在該元件上直接使用 register 綁定:

//範例使用的是 shadcn 的 Input元件
<Input
  placeholder="帳號"
  {...register("username", { required: "必填欄位" })}
/>

若為受控元件就必須出動 React Hook Form 的 Controller!!

//範例使用的是 MUI 的 TextField 元件
import { useForm, Controller } from "react-hook-form"
import TextField from "@mui/material/TextField"
import Button from "@mui/material/Button"

export default function DemoForm() {
  // 初始化 useForm
  const { control, handleSubmit } = useForm({
    defaultValues: { username: "" }
  })

  // 提交表單
  const onSubmit = (data: FormData) => {
    console.log("表單資料:", data)
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* Controller 將 RHF 與受控元件 TextField 連結 */}
      <Controller
        name="username" //欄位名稱,必要屬性
        control={control} //從 useForm 解構出來的 control 對象,必要屬性,提供欄位管理功能。
        rules={{ required: "必填欄位" }} //驗證規則 (Validation Rules),等同 register 的
          rules
        render={({ field, fieldState }) => ( //callback,必要屬性,接收 { field,
          fieldState, formState },回傳 JSX 元件,在這裡帶入受控元件。
          <TextField
            label="帳號"
            value={field.value}
            onChange={field.onChange}
            error={!!fieldState.error}
            helperText={fieldState.error?.message}
          />
        )}
      />
      <Button type="submit" variant="contained">
        送出
      </Button>
    </form>
  )
}

雖然 Controller 主要是為了應對受控元件,但我更傾向把它理解成 UI 元件與 React Hook Form 的媒介~
今天先這樣了,明天再接續說說表單驗證!


上一篇
DAY 09 招喚表單魔法陣 - React Hook Form (2) 安裝與使用
下一篇
DAY 11 防禦魔法 - React Hook Form + Yup 不做表單驗證是種戰爭罪
系列文
請問這是魔法嗎?前端轉職菜雞的修煉之路!14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言