- The following table contains information about properties which{" "}
- {isController ? "Controller" : "useController"} produces.
-
-
-
-
-
Object Name
-
{generic.name}
-
{generic.type}
-
{generic.description}
-
-
-
-
-
- field
-
-
- onChange
-
-
-
- {"(value: any) => void"}
-
-
-
-
A function which sends the input's value to the library.
-
-
- It should be assigned to the onChange prop of the
- input and value should{" "}
-
- not be undefined
-
- .
-
-
-
- This prop update{" "}
-
- formState
- {" "}
- and you should avoid manually invoke{" "}
-
- setValue
- {" "}
- or other API related to field update.
-
-
-
-
-
-
-
- field
-
-
- onBlur
-
-
- {"() => void"}
-
-
-
- A function which sends the input's onBlur event to the library.
- It should be assigned to the input's onBlur prop.
-
-
-
-
-
- field
-
-
- value
-
-
- unknown
-
-
-
The current value of the controlled component.
-
-
-
-
- field
-
-
- disabled
-
-
- boolean
-
-
-
The disabled state of the input.
-
-
-
-
- field
-
-
- name
-
-
- string
-
-
-
Input's name being registered.
-
-
-
-
- field
-
-
- ref
-
-
- React.Ref
-
-
-
- A ref used to connect hook form to the input. Assign{" "}
- ref to component's input ref to allow hook form to
- focus the error input.
-
-
-
-
-
- fieldState
-
-
- invalid
-
-
- boolean
-
-
-
Invalid state for current input.
-
-
-
-
- fieldState
-
-
- isTouched
-
-
- boolean
-
-
-
Touched state for current controlled input.
-
-
-
-
- fieldState
-
-
- isDirty
-
-
- boolean
-
-
-
Dirty state for current controlled input.
-
-
-
-
- fieldState
-
-
- error
-
-
- object
-
-
-
error for this specific input.
-
-
-
-
-
- >
- )
-}
-
-export default UseControllerMethods
diff --git a/src/components/UseFieldArray.tsx b/src/components/UseFieldArray.tsx
deleted file mode 100644
index 23bc17140..000000000
--- a/src/components/UseFieldArray.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import typographyStyles from "../styles/typography.module.css"
-import Footer from "./Footer"
-import containerStyles from "../styles/container.module.css"
-import UseFieldArrayContent from "./UseFieldArrayContent"
-import StarRepo from "./StarRepo"
-import { Menu, apiLinks } from "./Menu"
-
-export default function UseFieldArray() {
- return (
-
-
- useFieldArray
-
-
React hooks for Field Array
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
diff --git a/src/components/UseFieldArrayContent.tsx b/src/components/UseFieldArrayContent.tsx
deleted file mode 100644
index 3271b3a5c..000000000
--- a/src/components/UseFieldArrayContent.tsx
+++ /dev/null
@@ -1,297 +0,0 @@
-import generic from "../data/generic"
-import api from "../data/api"
-import CodeArea from "./CodeArea"
-import useFieldArray from "./codeExamples/useFieldArray"
-import typographyStyles from "../styles/typography.module.css"
-import tableStyles from "../styles/table.module.css"
-import TabGroup from "./TabGroup"
-import useFieldArrayConditional from "./codeExamples/useFieldArrayConditional"
-import useFieldArrayTS from "./codeExamples/useFieldArrayTS"
-import useFieldArrayFocus from "./codeExamples/useFieldArrayFocus"
-import Link from "next/link"
-import useFieldArrayPreview from "./codeExamples/useFieldArrayPreview"
-
-export default function UseFieldArrayContent() {
- return (
- <>
-
-
- useFieldArray automatically generates a unique
- identifier named id which is used for key{" "}
- prop. For more information why this is required:{" "}
-
- https://react.dev/learn/rendering-lists
-
-
-
- The field.id (and not index) must be added
- as the component key to prevent re-renders breaking the fields:
- )}
-
-// ❌ incorrect:
-{fields.map((field, index) => )}
-`}
- />
-
-
-
-
It's recommended to not stack actions one after another.
- {
- append({ test: 'test' });
- remove(0);
-}}
-
-// ✅ Better solution: the remove action is happened after the second render
-React.useEffect(() => {
- remove(0);
-}, [remove])
-
-onClick={() => {
- append({ test: 'test' });
-}}
- `}
- />
-
-
-
- Each useFieldArray is unique and has its own state
- update, which means you should not have multiple useFieldArray with
- the same name.
-
-
-
-
- Each input name needs to be unique, if you need to build checkbox or
- radio with the same name then use it with useController{" "}
- or Controller.
-
-
-
-
Does not support flat field array.
-
-
-
- When you append, prepend, insert and update the field array, the obj
- can't be empty object {} rather need to supply all your
- input's defaultValues.
-
-
-
-
-
-
TypeScript
-
-
-
-
- when register input name, you will have to cast them as{" "}
- const
-
- `}
- />
-
-
-
- we do not support circular reference. Refer to this{" "}
-
- Github issue
- {" "}
- for more detail.
-
-
-
-
- for nested field array, you will have to cast the field array by its
- name.
-
-
-
-
-
-
- Examples
-
-
-
-
-
-
-
-
-
-
Video
-
- The following video explains the basic usage of{" "}
- useFieldArray.
-
-
-
-
-
Tips
-
Custom Register
-
- You can also register inputs at Controller{" "}
- without the actual input. This makes useFieldArray quick
- and flexible to use with complex data structure or the actual data is
- not stored inside an input.
-
- There will be cases where you want to control the entire field array,
- which means each onChange reflects on the fields object.
-
-
- ();
- const { fields, append } = useFieldArray({
- control,
- name: "fieldArray"
- });
- const watchFieldArray = watch("fieldArray");
- const controlledFields = fields.map((field, index) => {
- return {
- ...field,
- ...watchFieldArray[index]
- };
- });
-
- return (
-
- );
-}`}
- />
- >
- )
-}
diff --git a/src/components/seo.tsx b/src/components/seo.tsx
index 00a77a798..47e64fdb9 100644
--- a/src/components/seo.tsx
+++ b/src/components/seo.tsx
@@ -1,48 +1,36 @@
import Head from "next/head"
+import { useRouter } from "next/router"
-const site = {
- siteMetadata: {
- title: `React Hook Form - Simple React forms validation`,
- description: `Performant, flexible and extensible forms with easy-to-use validation.`,
- author: `@bluebill1049`,
- siteUrl: "https://react-hook-form.com",
- languages: {
- langs: ["en", "es", "jp", "zh", "kr", "pt", "ru"],
- defaultLangKey: "en",
- },
- },
-}
+const SITE_URL = "https://react-hook-form.com"
+const DEFAULT_TITLE = "React Hook Form - Simple React forms validation"
+const DEFAULT_DESCRIPTION =
+ "Performant, flexible and extensible forms with easy-to-use validation."
+const OG_IMAGE =
+ "https://raw.githubusercontent.com/react-hook-form/documentation/master/src/images/react-hook-form-og.png"
function SEO({ title, description }: { title: string; description?: string }) {
- const metaDescription = description || site.siteMetadata.description
+ const router = useRouter()
+ const metaTitle = title || DEFAULT_TITLE
+ const metaDescription = description || DEFAULT_DESCRIPTION
+ const canonical = `${SITE_URL}${router.asPath.split(/[?#]/)[0]}`
return (
- {title || site.siteMetadata.title}
-
-
-
-
-
-
-
-
+ {metaTitle}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/src/content/docs/createFormControl.mdx b/src/content/docs/createFormControl.mdx
index b92f887ea..010f7954a 100644
--- a/src/content/docs/createFormControl.mdx
+++ b/src/content/docs/createFormControl.mdx
@@ -1,10 +1,10 @@
---
title: createFormControl
-description: Create form state and ready to be subscribed
+description: Create standalone React Hook Form state outside of a React component, useful for global or shared form state management across your app.
sidebar: apiLinks
---
-This function create the entire form state subscription and allow you to subscribe update with or without react component. You can use this function without the need of React Context api.
+This function creates the entire form state subscription and allows you to subscribe to updates with or without a React component. You can use this function without the need of the React Context API.
### Props
diff --git a/src/content/docs/formprovider.mdx b/src/content/docs/formprovider.mdx
index 3b66f769e..bc760f036 100644
--- a/src/content/docs/formprovider.mdx
+++ b/src/content/docs/formprovider.mdx
@@ -1,6 +1,6 @@
---
title: FormProvider
-description: A component to provide React Context
+description: Wrap your form tree with FormProvider to share useForm methods across deeply nested components without passing props manually.
sidebar: apiLinks
---
diff --git a/src/content/docs/usecontroller.mdx b/src/content/docs/usecontroller.mdx
new file mode 100644
index 000000000..b56f47f1b
--- /dev/null
+++ b/src/content/docs/usecontroller.mdx
@@ -0,0 +1,260 @@
+---
+title: useController
+description: React hook for building reusable controlled inputs with full access to field value, validation state, and form state from React Hook Form.
+sidebar: apiLinks
+---
+
+
+
+## \> `useController:` `(props?: UseControllerProps) => { field: object, fieldState: object, formState: object }`
+
+This custom hook powers [`Controller`](/docs/usecontroller/controller). Additionally, it shares the same props and methods as `Controller`. It's useful for creating reusable Controlled input.
+
+### Props
+
+---
+
+The following table contains information about the arguments for `useController`.
+
+| Name | Type | Required | Description |
+| ------------------ | ----------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `name` | [FieldPath](/ts#FieldPath) | ✓ | Unique name of your input. |
+| `control` | [Control](/ts#Control) | | [`control`](/docs/useform/control) object provided by invoking `useForm`. Optional when using `FormProvider`. |
+| `rules` | Object | | Validation rules in the same format for `register`, which includes: `required`, `min`, `max`, `minLength`, `maxLength`, `pattern`, `validate`.
`rules={{ required: true }}` |
+| `shouldUnregister` | boolean = false | | Input will be unregistered after unmount and defaultValues will be removed as well. **Note:** this prop should be avoided when using with `useFieldArray` as `unregister` function gets called after input unmount/remount and reorder. |
+| `disabled` | boolean = false | | `disabled` prop will be returned from `field` prop. Controlled input will be disabled and its value will be omitted from the submission data. |
+| `defaultValue` | unknown | | **Important:** Can not apply `undefined` to `defaultValue` or `defaultValues` at `useForm`.
You need to either set `defaultValue` at the field-level or `useForm`'s `defaultValues`. `undefined` is not a valid value. If you used `defaultValues` at `useForm`, skip using this prop.
If your form will invoke `reset` with default values, you will need to provide `useForm` with `defaultValues`.
|
+| `exact` | boolean = false | | This prop will enable an exact match for input name subscriptions, default to true. |
+
+### Return
+
+---
+
+The following table contains information about properties which `useController` produces.
+
+| Object Name | Name | Type | Description |
+| ------------ | -------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `field` | `onChange` | (value: any) => void | A function which sends the input's value to the library. It should be assigned to the `onChange` prop of the input and value should **not be `undefined`**. This prop updates [formState](/docs/useform/formstate) and you should avoid manually invoking [`setValue`](/docs/useform/setvalue) or other API related to field update. |
+| `field` | `onBlur` | () => void | A function which sends the input's onBlur event to the library. It should be assigned to the input's `onBlur` prop. |
+| `field` | `value` | unknown | The current value of the controlled component. |
+| `field` | `disabled` | boolean | The disabled state of the input. |
+| `field` | `name` | string | Input's name being registered. |
+| `field` | `ref` | React.Ref | A ref used to connect hook form to the input. Assign `ref` to component's input ref to allow hook form to focus the error input. |
+| `fieldState` | `invalid` | boolean | Invalid state for current input. |
+| `fieldState` | `isTouched` | boolean | Touched state for current controlled input. |
+| `fieldState` | `isDirty` | boolean | Dirty state for current controlled input. |
+| `fieldState` | `error` | object | error for this specific input. |
+| `formState` | `isDirty` | boolean | Set to `true` after the user modifies any of the inputs. **Important:** Make sure to provide all inputs' `defaultValues` at `useForm`, so hook form can have a single source of truth to compare whether the form is dirty. |
+| `formState` | `dirtyFields` | object | An object with the user-modified fields. Make sure to provide all inputs' `defaultValues` via `useForm`, so the library can compare against the `defaultValues`. |
+| `formState` | `touchedFields` | object | An object containing all the inputs the user has interacted with. |
+| `formState` | `defaultValues` | object | The value which has been set at [`useForm`](/docs/useform)'s `defaultValues` or updated `defaultValues` via [`reset`](/docs/useform/reset) API. |
+| `formState` | `isSubmitted` | boolean | Set to `true` after the form is submitted. Will remain `true` until the `reset` method is invoked. |
+| `formState` | `isSubmitSuccessful` | boolean | Indicate the form was successfully submitted without any runtime error. |
+| `formState` | `isSubmitting` | boolean | `true` if the form is currently being submitted. `false` otherwise. |
+| `formState` | `isLoading` | boolean | `true` if the form is currently loading async default values. **Important:** this prop is only applicable to async `defaultValues`. |
+| `formState` | `submitCount` | number | Number of times the form was submitted. |
+| `formState` | `isValid` | boolean | Set to `true` if the form doesn't have any errors. `setError` has no effect on `isValid` formState, `isValid` will always derived via the entire form validation result. |
+| `formState` | `isValidating` | boolean | Set to `true` during validation. |
+| `formState` | `validatingFields` | object | Capture fields which are getting async validation. |
+| `formState` | `errors` | object | An object with field errors. There is also an [ErrorMessage](/docs/useformstate/errormessage) component to retrieve error message easily. |
+| `formState` | `disabled` | boolean | Set to `true` if the form is disabled via the `disabled` prop in [`useForm`](/docs/useform#disabled). |
+
+### Examples {#example}
+
+---
+
+
+
+
+
+```javascript sandbox="https://codesandbox.io/s/usecontroller-checkboxes-99ld4"
+import * as React from "react"
+import { useController, useForm } from "react-hook-form"
+
+const Checkboxes = ({ options, control, name }) => {
+ const { field } = useController({
+ control,
+ name,
+ })
+ const [value, setValue] = React.useState(field.value || [])
+
+ return (
+ <>
+ {options.map((option, index) => (
+ {
+ const valueCopy = [...value]
+
+ // update checkbox value
+ valueCopy[index] = e.target.checked ? e.target.value : null
+
+ // send data to react hook form
+ field.onChange(valueCopy)
+
+ // update local state
+ setValue(valueCopy)
+ }}
+ key={option}
+ checked={value.includes(option)}
+ type="checkbox"
+ value={option}
+ />
+ ))}
+ >
+ )
+}
+
+export default function App() {
+ const { register, handleSubmit, control } = useForm({
+ defaultValues: {
+ controlled: [],
+ uncontrolled: [],
+ },
+ })
+ const onSubmit = (data) => console.log(data)
+
+ return (
+
+ )
+}
+```
+
+
+
+### Tips
+
+---
+
+- It's important to be aware of each prop's responsibility when working with external controlled components, such as MUI, AntD, Chakra UI. Its job is to spy on the input, report, and set its value.
+ - **onChange**: send data back to hook form
+ - **onBlur**: report that the input has been interacted with (focus and blur)
+ - **value**: set up input initial and updated value
+ - **ref**: allow input to be focused with error
+ - **name**: give input an unique name
+
+ It's fine to host your state and combined with `useController`.
+
+ ```javascript sandbox="https://codesandbox.io/s/usecontroller-own-state-wncet2?file=/src/App.tsx"
+ const { field } = useController();
+ const [value, setValue] = useState(field.value);
+
+ onChange={(event) => {
+ field.onChange(parseInt(event.target.value)) // data send back to hook form
+ setValue(event.target.value) // UI state
+ }}
+ ```
+
+- Do not `register` input again. This custom hook is designed to take care of the registration process.
+
+ ```javascript
+ const { field } = useController({ name: 'test' })
+
+ // ✅
+ // ❌ double up the registration
+ ```
+
+- It's ideal to use a single `useController` per component. If you need to use more than one, make sure you rename the prop. May want to consider using `Controller` instead.
+
+ ```javascript
+ const { field: input } = useController({ name: 'test' })
+ const { field: checkbox } = useController({ name: 'test1' })
+
+
+
+ ```
diff --git a/src/content/docs/usecontroller/controller.mdx b/src/content/docs/usecontroller/controller.mdx
index 4db8719a3..8b314b1f4 100644
--- a/src/content/docs/usecontroller/controller.mdx
+++ b/src/content/docs/usecontroller/controller.mdx
@@ -1,6 +1,6 @@
---
title: Controller
-description: Wrapper component for controlled inputs
+description: Wrapper component for integrating controlled external inputs like MUI, Chakra UI, and React-Select with React Hook Form validation.
sidebar: apiLinks
---
@@ -190,7 +190,7 @@ export default function App() {
---
-The following video showcases what's inside Controller and how its been built.
+The following video showcases what's inside Controller and how it was built.
diff --git a/src/content/docs/usefieldarray.mdx b/src/content/docs/usefieldarray.mdx
new file mode 100644
index 000000000..a50f3c9cc
--- /dev/null
+++ b/src/content/docs/usefieldarray.mdx
@@ -0,0 +1,526 @@
+---
+title: useFieldArray
+description: React hook for dynamic field arrays. Append, prepend, insert, remove, swap, move, update, and replace fields with optimized performance.
+sidebar: apiLinks
+---
+
+## \> `useFieldArray:` [UseFieldArrayProps](/ts#UseFieldArrayProps)
+
+Custom hook for working with Field Arrays (dynamic form). The motivation is to provide better user experience and performance. You can watch [this short video](https://www.youtube.com/watch?v=Q7lrHuUfgIs) to visualize the performance enhancement.
+
+### Props
+
+---
+
+| Name | Type | Required | Description |
+| ------------------ | ---------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `name` | string | ✓ | Name of the field array. **Note:** Dynamic names are not supported. |
+| `control` | Object | | [`control`](/docs/useform/control) object provided by `useForm`. It's optional if you are using `FormProvider`. |
+| `shouldUnregister` | boolean | | Whether Field Array will be unregistered after unmount. |
+| `keyName` | string = "id" | | Name of the attribute with autogenerated identifier to use as the `key` prop. This prop is no longer required and will be removed in the next major version. |
+| `rules` | Object | | The same validation `rules` API as for [`register`](/docs/useform/register), which includes: `required`, `minLength`, `maxLength`, `validate`. In case of validation error, the `root` property is appended to `formState.errors?.fieldArray?.root` of type [`FieldError`](/ts/#FieldError). **Important:** This is only applicable to **built-in** validation. |
+
+**Props example**
+
+```javascript sandbox="https://codesandbox.io/s/react-hook-form-usefieldarray-rules-iyejbp?file=/src/index.js"
+function FieldArray() {
+ const { control, register } = useForm();
+ const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({
+ control, // control props comes from useForm (optional: if you are using FormProvider)
+ name: "test", // unique name for your Field Array
+ });
+
+ return (
+ {fields.map((field, index) => (
+
+ ))}
+ );
+}
+```
+
+### Return
+
+---
+
+| Name | Type | Description |
+| --------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `fields` | object & \{ id: string \} | This `object` contains the `defaultValue` and `key` for your component. |
+| `append` | (obj: object \| object[], focusOptions) => void | Append input/inputs to the end of your fields and focus. The input value will be registered during this action. **Important:** append data is required and not partial. |
+| `prepend` | (obj: object \| object[], focusOptions) => void | Prepend input/inputs to the start of your fields and focus. The input value will be registered during this action. **Important:** prepend data is required and not partial. |
+| `insert` | (index: number, value: object \| object[], focusOptions) => void | Insert input/inputs at particular position and focus. **Important:** insert data is required and not partial. |
+| `swap` | (from: number, to: number) => void | Swap input/inputs position. |
+| `move` | (from: number, to: number) => void | Move input/inputs to another position. |
+| `update` | (index: number, obj: object) => void | Update input/inputs at a particular position, updated fields will get unmounted and remounted. If this is not desired behavior, please use [`setValue`](/docs/useform/setvalue) API instead. **Important:** update data is required and not partial. |
+| `replace` | (obj: object[]) => void | Replace the entire field array values. |
+| `remove` | (index?: number \| number[]) => void | Remove input/inputs at particular position, or remove all when no index provided. |
+
+### Rules {#rules}
+
+---
+
+- `useFieldArray` automatically generates a unique identifier named `id` which is used for `key` prop. For more information why this is required: [https://react.dev/learn/rendering-lists](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)
+
+ The `field.id` (and not `index`) must be added as the component key to prevent re-renders breaking the fields:
+
+ ```javascript
+ // ✅ correct:
+ {fields.map((field, index) => )}
+
+ // ❌ incorrect:
+ {fields.map((field, index) => )}
+ ```
+
+- It's recommended to not stack actions one after another.
+
+ ```javascript
+ onClick={() => {
+ append({ test: 'test' });
+ remove(0);
+ }}
+
+ // ✅ Better solution: the remove action is happened after the second render
+ React.useEffect(() => {
+ remove(0);
+ }, [remove])
+
+ onClick={() => {
+ append({ test: 'test' });
+ }}
+ ```
+
+- Each `useFieldArray` is unique and has its own state update, which means you should not have multiple useFieldArray with the same `name`.
+
+- Each input name needs to be unique, if you need to build checkbox or radio with the same name then use it with `useController` or `Controller`.
+
+- Does not support flat field array.
+
+- When you append, prepend, insert and update the field array, the obj can't be empty object `{}` rather need to supply all your input's defaultValues.
+
+ ```javascript
+ append() // ❌
+ append({}) // ❌
+ append({ firstName: "bill", lastName: "luo" }) // ✅
+ ```
+
+### TypeScript
+
+---
+
+- When registering an input `name`, you will have to cast them as `const`:
+
+ ```javascript
+
+ ```
+
+- Circular references are not supported. Refer to this [Github issue](https://github.com/react-hook-form/react-hook-form/issues/4055) for more detail.
+
+- For nested field arrays, you will have to cast the field array by its name:
+
+ ```javascript
+ const { fields } = useFieldArray({ name: `test.${index}.keyValue` as 'test.0.keyValue' });
+ ```
+
+### Examples {#example}
+
+---
+
+
+
+
+
+
+
+```javascript sandbox="https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn"
+import { useForm, useFieldArray } from "react-hook-form"
+
+function App() {
+ const { register, control, handleSubmit, reset, trigger, setError } = useForm(
+ {
+ // defaultValues: {}; you can populate the fields by this attribute
+ }
+ )
+ const { fields, append, remove } = useFieldArray({
+ control,
+ name: "test",
+ })
+
+ return (
+
+ )
+}
+```
+
+```tsx sandbox="https://codesandbox.io/s/calc-i231d"
+import * as React from "react"
+import { useForm, useFieldArray, useWatch, Control } from "react-hook-form"
+
+type FormValues = {
+ cart: {
+ name: string
+ price: number
+ quantity: number
+ }[]
+}
+
+const Total = ({ control }: { control: Control }) => {
+ const formValues = useWatch({
+ name: "cart",
+ control,
+ })
+ const total = formValues.reduce(
+ (acc, current) => acc + (current.price || 0) * (current.quantity || 0),
+ 0
+ )
+ return
+ )
+}
+```
+
+```javascript sandbox="https://codesandbox.io/s/usefieldarray-conditional-2wi6f"
+import React from "react"
+import { useForm, useWatch, useFieldArray, Control } from "react-hook-form"
+
+const ConditionField = ({ control, index, register }) => {
+ const output = useWatch({
+ name: "data",
+ control,
+ defaultValue: "yay! I am watching you :)",
+ })
+
+ return (
+ <>
+ {output[index]?.name === "bill" && (
+
+ )}
+
+ >
+ )
+}
+
+const UseFieldArrayUnregister = () => {
+ const { control, handleSubmit, register } = useForm({
+ defaultValues: {
+ data: [{ name: "test" }, { name: "test1" }, { name: "test2" }],
+ },
+ mode: "onSubmit",
+ shouldUnregister: false,
+ })
+ const { fields } = useFieldArray({
+ control,
+ name: "data",
+ })
+ const onSubmit = (data) => console.log(data)
+
+ return (
+
+ )
+}
+```
+
+```javascript
+import React from 'react';
+import { useForm, useFieldArray } from 'react-hook-form';
+
+const App = () => {
+ const { register, control } = useForm({
+ defaultValues: {
+ test: [{ value: '1' }, { value: '2' }],
+ },
+ });
+ const { fields, prepend, append } = useFieldArray({
+ name: 'test',
+ control,
+ });
+
+ return (
+
+ );
+};
+```
+
+
+
+### Video
+
+---
+
+
+
+### Tips
+
+---
+
+**Custom Register**
+
+You can also `register` inputs at `Controller` without the actual input. This makes `useFieldArray` quick and flexible to use with complex data structure or the actual data is not stored inside an input.
+
+```javascript sandbox="https://codesandbox.io/s/usefieldarray-virtual-input-v9wyw"
+import { useForm, useFieldArray, Controller, useWatch } from "react-hook-form"
+
+const ConditionalInput = ({ control, index, field }) => {
+ const value = useWatch({
+ name: "test",
+ control,
+ })
+
+ return (
+
+ value?.[index]?.checkbox === "on" ? : null
+ }
+ />
+ )
+}
+
+function App() {
+ const { control, register } = useForm()
+ const { fields, append, prepend } = useFieldArray({
+ control,
+ name: "test",
+ })
+
+ return (
+
+ )
+}
+```
+
+**Controlled Field Array**
+
+There will be cases where you want to control the entire field array, which means each onChange reflects on the `fields` object.
+
+```javascript sandbox="https://codesandbox.io/s/infallible-bush-c92l0?file=/src/App.tsx"
+import { useForm, useFieldArray } from "react-hook-form";
+
+export default function App() {
+ const { register, handleSubmit, control, watch } = useForm();
+ const { fields, append } = useFieldArray({
+ control,
+ name: "fieldArray"
+ });
+ const watchFieldArray = watch("fieldArray");
+ const controlledFields = fields.map((field, index) => {
+ return {
+ ...field,
+ ...watchFieldArray[index]
+ };
+ });
+
+ return (
+
+ );
+}
+```
diff --git a/src/content/docs/useform.mdx b/src/content/docs/useform.mdx
index 05a61efac..7756c9de1 100644
--- a/src/content/docs/useform.mdx
+++ b/src/content/docs/useform.mdx
@@ -1,6 +1,6 @@
---
title: useForm
-description: React hooks for form validation
+description: The primary React Hook Form hook. Initialize your form with validation rules, default values, and submission handling in a single call.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/clearerrors.mdx b/src/content/docs/useform/clearerrors.mdx
index 33087a17b..eea206c5d 100644
--- a/src/content/docs/useform/clearerrors.mdx
+++ b/src/content/docs/useform/clearerrors.mdx
@@ -1,6 +1,6 @@
---
title: clearErrors
-description: Clear form errors
+description: Manually clear validation errors for one field, an array of fields, or the entire React Hook Form without triggering re-validation.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/control.mdx b/src/content/docs/useform/control.mdx
index b6fef1336..866b2ade7 100644
--- a/src/content/docs/useform/control.mdx
+++ b/src/content/docs/useform/control.mdx
@@ -1,6 +1,6 @@
---
title: control
-description: Take control of the form
+description: The control object returned by useForm, required to register controlled inputs via the Controller component and useController hook.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/form.mdx b/src/content/docs/useform/form.mdx
index 012d5a652..c3bbe69ab 100644
--- a/src/content/docs/useform/form.mdx
+++ b/src/content/docs/useform/form.mdx
@@ -1,6 +1,6 @@
---
title: Form
-description: Take care of form submission
+description: React Hook Form's Form component handles submission to a URL or callback, with built-in loading, error, and success state management.
sidebar: apiLinks
---
@@ -46,7 +46,7 @@ All props are optional
-- If want to prepare or omit submission data, please use [`handleSubmit`](/docs/useform/handlesubmit) or `onSubmit`.
+- If you want to prepare or omit submission data, please use [`handleSubmit`](/docs/useform/handlesubmit) or `onSubmit`.
```javascript
const { handleSubmit, control } = useForm();
const onSubmit =(data) => callback(prepareData(data))
diff --git a/src/content/docs/useform/formstate.mdx b/src/content/docs/useform/formstate.mdx
index e17718333..5657c3320 100644
--- a/src/content/docs/useform/formstate.mdx
+++ b/src/content/docs/useform/formstate.mdx
@@ -1,6 +1,6 @@
---
title: formState
-description: State of the form
+description: Access real-time form state including isDirty, isValid, errors, isSubmitting, touchedFields, and dirtyFields from React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/getfieldstate.mdx b/src/content/docs/useform/getfieldstate.mdx
index e9c130548..9e670f50a 100644
--- a/src/content/docs/useform/getfieldstate.mdx
+++ b/src/content/docs/useform/getfieldstate.mdx
@@ -1,6 +1,6 @@
---
title: getFieldState
-description: State of the field
+description: Get the current validation and interaction state of a specific field — invalid, isDirty, isTouched, and error — from React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/getvalues.mdx b/src/content/docs/useform/getvalues.mdx
index 6005f5b06..4f044788a 100644
--- a/src/content/docs/useform/getvalues.mdx
+++ b/src/content/docs/useform/getvalues.mdx
@@ -1,6 +1,6 @@
---
title: getValues
-description: Get form values
+description: Read current form values without subscribing to re-renders. Retrieve a single field, multiple fields, or the entire form data object.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/handlesubmit.mdx b/src/content/docs/useform/handlesubmit.mdx
index 6ab2501dd..34ea940d9 100644
--- a/src/content/docs/useform/handlesubmit.mdx
+++ b/src/content/docs/useform/handlesubmit.mdx
@@ -1,6 +1,6 @@
---
title: handleSubmit
-description: Ready to send to the server
+description: Validate form inputs and invoke your submit callback with typed form data, or pass errors to an error handler on validation failure.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/register.mdx b/src/content/docs/useform/register.mdx
index 7797c9d12..c2f736c29 100644
--- a/src/content/docs/useform/register.mdx
+++ b/src/content/docs/useform/register.mdx
@@ -1,6 +1,6 @@
---
title: register
-description: Register uncontrolled/controlled inputs
+description: Register an input with React Hook Form to enable validation, value tracking, and form submission. Supports text, checkbox, select, and more.
sidebar: apiLinks
---
@@ -106,7 +106,7 @@ By selecting the register option, the API table below will get updated.
(except for native radio and checkbox inputs).
- Name must not start with a number or use numbers as standalone keys, and should avoid special characters.
+ Names must not start with a number or use numbers as standalone keys, and should avoid special characters.
For TypeScript consistency, only dot syntax is supported—bracket syntax ([]) will not work for array form values.
```javascript
diff --git a/src/content/docs/useform/reset.mdx b/src/content/docs/useform/reset.mdx
index 88acaa9b3..27c6cab60 100644
--- a/src/content/docs/useform/reset.mdx
+++ b/src/content/docs/useform/reset.mdx
@@ -1,6 +1,6 @@
---
title: reset
-description: Reset form state and values
+description: Reset the entire form to default values, clearing all errors, dirty fields, and touched state in React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/resetfield.mdx b/src/content/docs/useform/resetfield.mdx
index d1ccd24ae..548803cae 100644
--- a/src/content/docs/useform/resetfield.mdx
+++ b/src/content/docs/useform/resetfield.mdx
@@ -1,6 +1,6 @@
---
title: resetField
-description: Reset field state and value
+description: Reset a single field's value and state — errors, dirty, and touched — independently without resetting the entire React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/seterror.mdx b/src/content/docs/useform/seterror.mdx
index 3c2af0efe..fdcccf782 100644
--- a/src/content/docs/useform/seterror.mdx
+++ b/src/content/docs/useform/seterror.mdx
@@ -1,6 +1,6 @@
---
title: setError
-description: Manually set an input error
+description: Manually set a validation error on one or multiple fields, with support for server-side and custom errors in React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/setfocus.mdx b/src/content/docs/useform/setfocus.mdx
index 779d3b7c7..30132fa1c 100644
--- a/src/content/docs/useform/setfocus.mdx
+++ b/src/content/docs/useform/setfocus.mdx
@@ -1,6 +1,6 @@
---
title: setFocus
-description: Manually set an input focus
+description: Programmatically focus any registered input field, with an option to also select its current value in React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/setvalue.mdx b/src/content/docs/useform/setvalue.mdx
index 9791fd4d2..d9133d376 100644
--- a/src/content/docs/useform/setvalue.mdx
+++ b/src/content/docs/useform/setvalue.mdx
@@ -1,6 +1,6 @@
---
title: setValue
-description: Update field value
+description: Dynamically update a registered field's value with options to trigger validation, mark the field dirty, or set it as touched.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/setvalues.mdx b/src/content/docs/useform/setvalues.mdx
new file mode 100644
index 000000000..1c5a76231
--- /dev/null
+++ b/src/content/docs/useform/setvalues.mdx
@@ -0,0 +1,128 @@
+---
+title: setValues
+description: Update multiple React Hook Form field values at once using an object or a callback that receives the current form values and returns changes.
+sidebar: apiLinks
+---
+
+## \> `setValues:` (value: Partial\ | ((data: TFieldValues) => Partial\), options?: SetValueConfig) => void
+
+This function allows you to dynamically set multiple field values at once and have the options to validate and update the form state. It also accepts a callback function that receives the current form values, making it easy to derive the next state from the existing one.
+
+### Props
+
+---
+
+| Name | | Description |
+| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `value` Partial\ \| (data: TFieldValues) => Partial\ | | An object containing the field values to update, or a callback function that receives the current form values and returns the updated values. This argument is required. |
+| `options` | `shouldValidate` boolean |
Whether to compute if your input is valid or not (subscribed to errors).
Whether to compute if your entire form is valid or not (subscribed to isValid).
|
+| | `shouldDirty` boolean |
Whether to compute if your input is dirty or not against your `defaultValues` (subscribed to dirtyFields).
Whether to compute if your entire form is dirty or not against your `defaultValues` (subscribed to isDirty).
|
+| | `shouldTouch` boolean | Whether to set the updated inputs to be touched. |
+
+
+
+- When using the callback form, the function receives a snapshot of the current form values and should return only the fields you want to update.
+
+- This method does not reset the form. Use [`reset`](/docs/useform/reset) if you need to reinitialize `defaultValues`.
+
+
+
+### Examples
+
+---
+
+**Basic**
+
+```javascript
+import { useForm } from "react-hook-form"
+
+const App = () => {
+ const { register, setValues } = useForm({
+ defaultValues: {
+ firstName: "",
+ lastName: "",
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+**Callback (derive next state from current values)**
+
+```javascript
+import { useForm } from "react-hook-form"
+
+const App = () => {
+ const { register, setValues } = useForm({
+ defaultValues: {
+ name: "",
+ count: 0,
+ },
+ })
+
+ return (
+
+ )
+}
+```
+
+**With options**
+
+```javascript
+import { useForm } from "react-hook-form"
+
+const App = () => {
+ const { register, setValues } = useForm({
+ defaultValues: {
+ firstName: "",
+ lastName: "",
+ },
+ })
+
+ return (
+
+ )
+}
+```
diff --git a/src/content/docs/useform/subscribe.mdx b/src/content/docs/useform/subscribe.mdx
index 954da6d3a..25de865a9 100644
--- a/src/content/docs/useform/subscribe.mdx
+++ b/src/content/docs/useform/subscribe.mdx
@@ -1,6 +1,6 @@
---
title: subscribe
-description: Subscribe to form state update without render
+description: Subscribe to React Hook Form state changes outside the render cycle — ideal for analytics, side effects, and non-React integrations.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/trigger.mdx b/src/content/docs/useform/trigger.mdx
index 6b865df07..07947aae3 100644
--- a/src/content/docs/useform/trigger.mdx
+++ b/src/content/docs/useform/trigger.mdx
@@ -1,6 +1,6 @@
---
title: trigger
-description: Trigger validation across the form
+description: Manually trigger validation for one field, a list of fields, or the entire React Hook Form without submitting.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/unregister.mdx b/src/content/docs/useform/unregister.mdx
index 30bd21518..7116e99b4 100644
--- a/src/content/docs/useform/unregister.mdx
+++ b/src/content/docs/useform/unregister.mdx
@@ -1,6 +1,6 @@
---
title: unregister
-description: Unregister uncontrolled/controlled inputs
+description: Remove a registered input from React Hook Form, optionally preserving its value, error, dirty, or touched state on unmount.
sidebar: apiLinks
---
diff --git a/src/content/docs/useform/watch.mdx b/src/content/docs/useform/watch.mdx
index 3cf479ec4..ea0089059 100644
--- a/src/content/docs/useform/watch.mdx
+++ b/src/content/docs/useform/watch.mdx
@@ -1,6 +1,6 @@
---
title: watch
-description: Subscribe to input changes
+description: Subscribe to one or more input value changes and trigger re-renders. Useful for conditional form logic and dependent field calculations.
sidebar: apiLinks
---
diff --git a/src/content/docs/useformcontext.mdx b/src/content/docs/useformcontext.mdx
index 5b59d12e9..47da6095e 100644
--- a/src/content/docs/useformcontext.mdx
+++ b/src/content/docs/useformcontext.mdx
@@ -1,6 +1,6 @@
---
title: useFormContext
-description: React Context API for hook form
+description: Access all useForm methods deep in the component tree without prop drilling, using React Hook Form's built-in context API.
sidebar: apiLinks
---
diff --git a/src/content/docs/useformstate.mdx b/src/content/docs/useformstate.mdx
index b29e917ee..e3b3a579d 100644
--- a/src/content/docs/useformstate.mdx
+++ b/src/content/docs/useformstate.mdx
@@ -1,6 +1,6 @@
---
title: useFormState
-description: Subscribe to form state update
+description: Subscribe to specific form state properties and isolate re-renders at the component level for better performance in large React Hook Forms.
sidebar: apiLinks
---
diff --git a/src/content/docs/useformstate/errormessage.mdx b/src/content/docs/useformstate/errormessage.mdx
index 69227c022..7c2b08400 100644
--- a/src/content/docs/useformstate/errormessage.mdx
+++ b/src/content/docs/useformstate/errormessage.mdx
@@ -1,6 +1,6 @@
---
title: ErrorMessage
-description: An error message component to handle errors
+description: Render validation error messages for a registered field. Supports multiple errors per field and custom message rendering in React Hook Form.
sidebar: apiLinks
---
diff --git a/src/content/docs/useformstate/formstatesubscribe.mdx b/src/content/docs/useformstate/formstatesubscribe.mdx
index e2c8abe07..481546def 100644
--- a/src/content/docs/useformstate/formstatesubscribe.mdx
+++ b/src/content/docs/useformstate/formstatesubscribe.mdx
@@ -1,12 +1,12 @@
---
title: FormStateSubscribe
-description: Component to subscribe to form state update
+description: A renderless React component that subscribes to form state changes and re-renders children only when the relevant state updates occur.
sidebar: apiLinks
---
## \> `FormStateSubscribe:` Component
-A React Hook Form component that provides the same functionality as `uesFormState`, but in component form. Instead of using the hook inside another component, you can use `` directly in your JSX to subscribe to and render form state.
+A React Hook Form component that provides the same functionality as `useFormState`, but in component form. Instead of using the hook inside another component, you can use `` directly in your JSX to subscribe to and render form state.
### Props
diff --git a/src/content/docs/uselens.mdx b/src/content/docs/uselens.mdx
index 50b90e8f6..e853861d7 100644
--- a/src/content/docs/uselens.mdx
+++ b/src/content/docs/uselens.mdx
@@ -1,6 +1,6 @@
---
title: useLens
-description: Type-safe functional lenses for React Hook Form
+description: Type-safe functional lenses that scope form context to a nested field path, reducing boilerplate in deeply nested React Hook Forms.
sidebar: apiLinks
---
diff --git a/src/content/docs/usewatch.mdx b/src/content/docs/usewatch.mdx
index 06977de2a..5244e3fd8 100644
--- a/src/content/docs/usewatch.mdx
+++ b/src/content/docs/usewatch.mdx
@@ -1,6 +1,6 @@
---
title: useWatch
-description: React Hook for subscribing to input changes
+description: Subscribe to input value changes with isolated component-level re-renders, offering better performance than watch for large React Hook Forms.
sidebar: apiLinks
---
diff --git a/src/content/docs/usewatch/watch.mdx b/src/content/docs/usewatch/watch.mdx
index bf327bb5b..0fc3f24c0 100644
--- a/src/content/docs/usewatch/watch.mdx
+++ b/src/content/docs/usewatch/watch.mdx
@@ -1,6 +1,6 @@
---
title: Watch
-description: Watch component for subscribing to input changes
+description: A React component that subscribes to form input changes and re-renders only its children, scoping updates for better performance.
sidebar: apiLinks
---
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index a5f79e378..5045e8f95 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -34,7 +34,6 @@ function App({ Component, pageProps }: AppProps) {
return (
<>
- React Hook Form - Simple React forms validation
+
) => (
const AboutUs = () => {
return (
-
+
diff --git a/src/pages/dev-tools.tsx b/src/pages/dev-tools.tsx
index 9f0a61812..a5cca758c 100644
--- a/src/pages/dev-tools.tsx
+++ b/src/pages/dev-tools.tsx
@@ -1,11 +1,13 @@
import Layout from "../components/layout"
import Seo from "../components/seo"
import DevTools from "../components/DevTools"
-import api from "../data/api"
const Api = () => (
-
+
)
diff --git a/src/pages/docs.tsx b/src/pages/docs.tsx
index 1be303d55..caf1b3511 100644
--- a/src/pages/docs.tsx
+++ b/src/pages/docs.tsx
@@ -5,7 +5,10 @@ import ApiGallery from "../components/ApiGallery"
const Api = () => (
-
+
)
diff --git a/src/pages/docs/usecontroller.tsx b/src/pages/docs/usecontroller.tsx
deleted file mode 100644
index 86299b9b9..000000000
--- a/src/pages/docs/usecontroller.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Seo from "../../components/seo"
-import Layout from "../../components/layout"
-import UseControllerContent from "../../components/UseController"
-
-export default function Usecontroller() {
- return (
-
-
-
-
- )
-}
diff --git a/src/pages/docs/usefieldarray.tsx b/src/pages/docs/usefieldarray.tsx
deleted file mode 100644
index 1d6df5e28..000000000
--- a/src/pages/docs/usefieldarray.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Seo from "../../components/seo"
-import Layout from "../../components/layout"
-import UseFieldArrayContent from "../../components/UseFieldArray"
-
-export default function UseFieldArray() {
- return (
-
-
-
-
- )
-}
diff --git a/src/pages/media.tsx b/src/pages/media.tsx
index e4008d9b7..11013fa7f 100644
--- a/src/pages/media.tsx
+++ b/src/pages/media.tsx
@@ -9,7 +9,10 @@ import Footer from "../components/Footer"
const Media = () => {
return (
-
+