# useFormContext

> Access all useForm methods deep in the component tree without prop drilling, using React Hook Form's built-in context API.

Source: https://react-hook-form.com/docs/useformcontext

## `useFormContext:` () => [UseFormReturn](https://react-hook-form.com/ts#UseFormReturn)

This custom hook allows you to access the form context. `useFormContext` is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop.

### Return

---

This hook returns all the `useForm` methods and props.

```javascript
const methods = useForm()

<FormProvider {...methods} /> // all the useForm return props

const methods = useFormContext() // retrieve those props
```

> **Important: Rules**
>   You need to wrap your form with the [`FormProvider`](https://react-hook-form.com/docs/formprovider)
>   component for `useFormContext` to work properly.
>
> Outside a `FormProvider`, `useFormContext()` returns `null` even though its return type isn't nullable, so destructuring it throws `Cannot destructure property 'register' of ... as it is null`.
>
> To avoid repeating your form type, wrap it in a typed hook. The generic is only a type assertion; it isn't checked against the form the provider actually holds.
>
> ```tsx
> export const useProfileForm = () => useFormContext<ProfileFormValues>()
> ```
>
> _(since v7.44.0)_ Supports a third generic, `useFormContext<TFieldValues, TContext, TTransformedValues>()`, to type the resolver's transformed output separately from the raw form values and context type.
>
> If you need to subscribe to form state values like `errors`, `isDirty`, or
> `dirtyFields` inside a `FormProvider` tree, use
> [`useFormState`](https://react-hook-form.com/docs/useformstate) instead of destructuring `formState`
> from `useFormContext()`. `formState` is wrapped in a Proxy that only tracks
> the fields you actually read during render — destructuring `formState` and
> reading a property later (e.g. in a callback), or reading it conditionally,
> won't register a subscription, so the component won't re-render when that
> value changes.
>

### Example

---

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)

```javascript
import { useEffect } from "react"
import { useForm, FormProvider, useFormContext } from "react-hook-form"

export default function App() {
  const methods = useForm()
  const onSubmit = (data) => console.log(data)
  const { register, reset } = methods

  useEffect(() => {
    reset({
      name: "data",
    })
  }, [reset]) // ❌ never put `methods` as a dependency

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <NestedInput />
        <input {...register("name")} />
        <input type="submit" />
      </form>
    </FormProvider>
  )
}

function NestedInput() {
  const { register } = useFormContext() // retrieve all hook methods
  return <input {...register("test")} />
}
```

### Tips

---

- Wrap components that use `useFormContext` in a small test helper, so you can render them alone in unit tests:

  ```tsx
  import { render } from "@testing-library/react"

  function renderWithForm(ui: React.ReactElement, defaultValues = {}) {
    function Wrapper({ children }: { children: React.ReactNode }) {
      const methods = useForm({ defaultValues })
      return <FormProvider {...methods}>{children}</FormProvider>
    }
    return render(ui, { wrapper: Wrapper })
  }
  ```

- `useFormContext` couples a component to one form shape. For an input that you reuse in many forms, take `name` (and optionally `control`) as props and use [`useController`](https://react-hook-form.com/docs/usecontroller), or look at [`useLens`](https://react-hook-form.com/docs/uselens).
- Use the context only for the methods you need. For example, `const { register } = useFormContext()` in a leaf input. Read state with [`useFormState`](https://react-hook-form.com/docs/useformstate) and values with [`useWatch`](https://react-hook-form.com/docs/usewatch).

### Troubleshooting

---

#### `Cannot destructure property 'register' of 'useFormContext(...)' as it is null`

**Why it happens:**

`useFormContext()` returns `null` outside a [`FormProvider`](https://react-hook-form.com/docs/formprovider). The exact wording depends on your bundler, but the message always ends in `as it is null`.

**Fix:**

Render the component inside a `FormProvider` that receives the whole `useForm` return value:

```javascript
const methods = useForm()

<FormProvider {...methods}>
  <NestedInput />
</FormProvider>
```

#### `handleSubmit is not a function` (or another method is `undefined`)

**Why it happens:**

Only some methods were passed to `FormProvider`, for example `<FormProvider register={register}>`. `useFormContext()` returns exactly what the provider received, so the other methods are missing.

**Fix:**

Spread the whole `useForm` return value: `<FormProvider {...methods}>`.

#### A field inside a nested `FormProvider` is missing from the submitted data

**Why it happens:**

`useFormContext` uses the nearest `FormProvider`. When one provider is rendered inside another, fields under the inner one register with the inner form, and the outer form's `handleSubmit` never sees them.

**Fix:**

Use one `FormProvider` per form. To show two forms on one page, render the providers next to each other, not one inside the other.
