安裝
安裝 React Hook Form 只需一個指令即可開始使用。
npm install react-hook-form
範例
以下程式碼片段展示了一個基本用法範例
import { useForm, SubmitHandler } from "react-hook-form"type Inputs = {example: stringexampleRequired: string}export default function App() {const {register,handleSubmit,watch,formState: { errors },} = useForm<Inputs>()const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data)console.log(watch("example")) // watch input value by passing the name of itreturn (/* "handleSubmit" will validate your inputs before invoking "onSubmit" */<form onSubmit={handleSubmit(onSubmit)}>{/* register your input into the hook by invoking the "register" function */}<input defaultValue="test" {...register("example")} />{/* include validation with required or other standard HTML validation rules */}<input {...register("exampleRequired", { required: true })} />{/* errors will return when field validation fails */}{errors.exampleRequired && <span>This field is required</span>}<input type="submit" /></form>)}
React 網頁應用程式影片教學
此影片教學說明了 React Hook Form 的基本用法和概念。
註冊欄位
React Hook Form 的一個關鍵概念是將您的組件註冊
到 hook 中。這將使其值可用於表單驗證和提交。
注意:每個欄位都必須有一個 name
作為註冊過程的鍵值。
import ReactDOM from "react-dom"import { useForm, SubmitHandler } from "react-hook-form"enum GenderEnum {female = "female",male = "male",other = "other",}interface IFormInput {firstName: stringgender: GenderEnum}export default function App() {const { register, handleSubmit } = useForm<IFormInput>()const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><label>First Name</label><input {...register("firstName")} /><label>Gender Selection</label><select {...register("gender")}><option value="female">female</option><option value="male">male</option><option value="other">other</option></select><input type="submit" /></form>)}
套用驗證
React Hook Form 透過與現有的 HTML 表單驗證標準保持一致,讓表單驗證變得容易。
支援的驗證規則列表
- required(必填)
- min(最小值)
- max(最大值)
- minLength(最小長度)
- maxLength(最大長度)
- pattern(模式)
- validate(驗證)
您可以在register 章節中閱讀有關每個規則的更多詳細資訊。
import { useForm, SubmitHandler } from "react-hook-form"interface IFormInput {firstName: stringlastName: stringage: number}export default function App() {const { register, handleSubmit } = useForm<IFormInput>()const onSubmit: SubmitHandler<IFormInput> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName", { required: true, maxLength: 20 })} /><input {...register("lastName", { pattern: /^[A-Za-z]+$/i })} /><input type="number" {...register("age", { min: 18, max: 99 })} /><input type="submit" /></form>)}
整合現有表單
整合現有表單應該很簡單。重要的步驟是註冊
組件的 ref
並將相關的 props 分派給您的輸入框。
import { Path, useForm, UseFormRegister, SubmitHandler } from "react-hook-form"interface IFormValues {"First Name": stringAge: number}type InputProps = {label: Path<IFormValues>register: UseFormRegister<IFormValues>required: boolean}// The following component is an example of your existing Input Componentconst Input = ({ label, register, required }: InputProps) => (<><label>{label}</label><input {...register(label, { required })} /></>)// you can use React.forwardRef to pass the ref tooconst Select = React.forwardRef<HTMLSelectElement,{ label: string } & ReturnType<UseFormRegister<IFormValues>>>(({ onChange, onBlur, name, label }, ref) => (<><label>{label}</label><select name={name} ref={ref} onChange={onChange} onBlur={onBlur}><option value="20">20</option><option value="30">30</option></select></>))const App = () => {const { register, handleSubmit } = useForm<IFormValues>()const onSubmit: SubmitHandler<IFormValues> = (data) => {alert(JSON.stringify(data))}return (<form onSubmit={handleSubmit(onSubmit)}><Input label="First Name" register={register} required /><Select label="Age" {...register("Age")} /><input type="submit" /></form>)}
與 UI 函式庫整合
React Hook Form 讓與外部 UI 組件庫整合變得容易。如果組件沒有公開輸入框的 ref
,那麼您應該使用 Controller 組件,它將負責註冊過程。
import Select from "react-select"import { useForm, Controller, SubmitHandler } from "react-hook-form"import { Input } from "@material-ui/core"interface IFormInput {firstName: stringlastName: stringiceCreamType: { label: string; value: string }}const App = () => {const { control, handleSubmit } = useForm({defaultValues: {firstName: "",lastName: "",iceCreamType: {},},})const onSubmit: SubmitHandler<IFormInput> = (data) => {console.log(data)}return (<form onSubmit={handleSubmit(onSubmit)}><Controllername="firstName"control={control}render={({ field }) => <Input {...field} />}/><Controllername="iceCreamType"control={control}render={({ field }) => (<Select{...field}options={[{ value: "chocolate", label: "Chocolate" },{ value: "strawberry", label: "Strawberry" },{ value: "vanilla", label: "Vanilla" },]}/>)}/><input type="submit" /></form>)}
整合受控輸入
這個函式庫擁抱非受控組件和原生 HTML 輸入框。 然而,很難避免使用外部受控組件,例如 React-Select、AntD 和 MUI。 為了簡化這一點,我們提供了一個包裝器組件 Controller 來簡化整合過程,同時仍然讓您可以自由使用自定義註冊。
使用組件 API
import { useForm, Controller, SubmitHandler } from "react-hook-form"import { TextField, Checkbox } from "@material-ui/core"interface IFormInputs {TextField: stringMyCheckbox: boolean}function App() {const { handleSubmit, control, reset } = useForm<IFormInputs>({defaultValues: {MyCheckbox: false,},})const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><Controllername="MyCheckbox"control={control}rules={{ required: true }}render={({ field }) => <Checkbox {...field} />}/><input type="submit" /></form>)}
使用 Hooks API
import * as React from "react"import { useForm, useController, UseControllerProps } from "react-hook-form"type FormValues = {FirstName: string}function Input(props: UseControllerProps<FormValues>) {const { field, fieldState } = useController(props)return (<div><input {...field} placeholder={props.name} /><p>{fieldState.isTouched && "Touched"}</p><p>{fieldState.isDirty && "Dirty"}</p><p>{fieldState.invalid ? "invalid" : "valid"}</p></div>)}export default function App() {const { handleSubmit, control } = useForm<FormValues>({defaultValues: {FirstName: "",},mode: "onChange",})const onSubmit = (data: FormValues) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><Input control={control} name="FirstName" rules={{ required: true }} /><input type="submit" /></form>)}
與全域狀態整合
這個函式庫不需要您依賴狀態管理函式庫,但您可以輕鬆地與它們整合。
import { useForm } from "react-hook-form"import { connect } from "react-redux"import updateAction from "./actions"export default function App(props) {const { register, handleSubmit, setValue } = useForm({defaultValues: {firstName: "",lastName: "",},})// Submit your data into Redux storeconst onSubmit = (data) => props.updateAction(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName")} /><input {...register("lastName")} /><input type="submit" /></form>)}// Connect your component with reduxconnect(({ firstName, lastName }) => ({ firstName, lastName }),updateAction)(YourForm)
處理錯誤
React Hook Form 提供了一個 errors
物件來顯示表單中的錯誤。 errors
的類型將返回給定的驗證約束。以下範例展示了一個必填驗證規則。
import { useForm } from "react-hook-form"export default function App() {const {register,formState: { errors },handleSubmit,} = useForm()const onSubmit = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input{...register("firstName", { required: true })}aria-invalid={errors.firstName ? "true" : "false"}/>{errors.firstName?.type === "required" && (<p role="alert">First name is required</p>)}<input{...register("mail", { required: "Email Address is required" })}aria-invalid={errors.mail ? "true" : "false"}/>{errors.mail && <p role="alert">{errors.mail.message}</p>}<input type="submit" /></form>)}
與服務整合
要將 React Hook Form 與服務整合,您可以使用函式庫內建的提交處理功能。<Form />
組件允許您輕鬆地將表單數據發送到 API 端點或其他服務。深入了解 Form 組件。
import { Form } from "react-hook-form"function App() {const { register, control } = useForm()return (<Formaction="/api/save" // Send post request with the FormData// encType={'application/json'} you can also switch to json objectonSuccess={() => {alert("Your application is updated.")}}onError={() => {alert("Submission has failed.")}}control={control}><input {...register("firstName", { required: true })} /><input {...register("lastName", { required: true })} /><button>Submit</button></Form>)}
結構描述驗證
我們也支援基於結構描述的表單驗證,使用 Yup、Zod、Superstruct 和 Joi,您可以將您的 schema
作為可選配置傳遞給 useForm。它將根據結構描述驗證您的輸入數據,並返回 errors 或有效的結果。
步驟 1:將 Yup
安裝到您的項目中。
npm install @hookform/resolvers yup
步驟 2:準備您的驗證結構描述並使用 React Hook Form 註冊輸入框。
import { useForm } from "react-hook-form"import { yupResolver } from "@hookform/resolvers/yup"import * as yup from "yup"const schema = yup.object({firstName: yup.string().required(),age: yup.number().positive().integer().required(),}).required()export default function App() {const {register,handleSubmit,formState: { errors },} = useForm({resolver: yupResolver(schema),})const onSubmit = (data) => console.log(data)return (<form onSubmit={handleSubmit(onSubmit)}><input {...register("firstName")} /><p>{errors.firstName?.message}</p><input {...register("age")} /><p>{errors.age?.message}</p><input type="submit" /></form>)}
React Native
您將在 React Native 中獲得相同的效能提升和增強。要與輸入組件整合,您可以使用 Controller
包裝它。
import { Text, View, TextInput, Button, Alert } from "react-native"import { useForm, Controller } from "react-hook-form"export default function App() {const {control,handleSubmit,formState: { errors },} = useForm({defaultValues: {firstName: "",lastName: "",},})const onSubmit = (data) => console.log(data)return (<View><Controllercontrol={control}rules={{required: true,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="First name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="firstName"/>{errors.firstName && <Text>This is required.</Text>}<Controllercontrol={control}rules={{maxLength: 100,}}render={({ field: { onChange, onBlur, value } }) => (<TextInputplaceholder="Last name"onBlur={onBlur}onChangeText={onChange}value={value}/>)}name="lastName"/><Button title="Submit" onPress={handleSubmit(onSubmit)} /></View>)}
TypeScript
React Hook Form 是使用 TypeScript
建構的,您可以定義一個 FormData
類型來支援表單值。
import * as React from "react"import { useForm } from "react-hook-form"type FormData = {firstName: stringlastName: string}export default function App() {const {register,setValue,handleSubmit,formState: { errors },} = useForm<FormData>()const onSubmit = handleSubmit((data) => console.log(data))// firstName and lastName will have correct typereturn (<form onSubmit={onSubmit}><label>First Name</label><input {...register("firstName")} /><label>Last Name</label><input {...register("lastName")} /><buttontype="button"onClick={() => {setValue("lastName", "luo") // ✅setValue("firstName", true) // ❌: true is not stringerrors.bill // ❌: property bill does not exist}}>SetValue</button></form>)}
設計與理念
React Hook Form 的設計和理念著重於使用者和開發者體驗。該函式庫旨在透過微調效能和改善無障礙功能,為使用者提供更順暢的互動體驗。一些效能增強功能包括
- 透過代理引入表單狀態訂閱模型
- 避免不必要的計算
- 在需要時隔離組件重新渲染
總體而言,它改善了使用者與應用程式互動時的使用者體驗。 至於開發者,我們引入了內建驗證,並與 HTML 標準緊密結合,允許使用強大的驗證方法和與結構描述驗證原生整合來進一步擴展。 此外,在 TypeScript 的幫助下,擁有一個強類型檢查的表單可以提供早期的建構時反饋,以幫助和引導開發者建構強大的表單解決方案。
以下由 Bill 發表的演講展示了一些想法和設計模式
感謝您的支持
如果您覺得 React Hook Form 在您的項目中有用,請考慮給它點星並支持它。