# createFormControl

> Create standalone React Hook Form state outside of a React component, useful for global or shared form state management across your app.

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

## `createFormControl:` ([UseFormProps](https://react-hook-form.com/ts#UseFormProps)) => object _(since v7.55.0)_

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 needing the React Context API.

### Props

---

| Name       | Type                        | Description    |
| ---------- | --------------------------- | -------------- |
| `...props` | `Object` | `UseFormProps` |

### Return

---

| Name          | Type                           | Description                                                                               |
| ------------- | ------------------------------ | ----------------------------------------------------------------------------------------- |
| `formControl` | `Object`    | control object for `useForm` hook                                                         |
| `control`     | `Object`    | control object for `useController`, `useFormState`, `useWatch`                            |
| `subscribe`   | `Function`  | function to [subscribe](https://react-hook-form.com/docs/useform/subscribe) for form state updates without rendering |
| `...returns`  | `Functions` | `useForm` return methods                                                                  |

> **Important: Notes**
>   - This function is completely optional; you can consider using this instead of
>   the `useFormContext` API. - You may find it useful if you would like to
>   subscribe to `formState` while skipping React re-renders.

> **Important: Rules**
>
> - You should either use this API or the Context API
>
>   ```tsx
>   const props = createFormControl()
> 
>   <FormProvider {...props} /> // ❌ You don't need a provider
> 
>   <input {...props.register("name")} /> // ✅ Use method directly from createFormControl
>   ```
>
> - Create the control once. Passing a new instance to `useForm({ formControl })` re-initializes the form. A control created at module scope is a single form shared by every component that uses it and, during server rendering, by every request. For one form per component instance, create it lazily:
>
>   ```tsx
>   const [form] = useState(() => createFormControl({ defaultValues }))
>   const { register } = useForm({ formControl: form.formControl })
>   ```
>

### Examples

---

**Setup**

```javascript
const { formControl, control, handleSubmit, register } = createFormControl({
  mode: "onChange",
  defaultValues: {
    firstName: "Bill",
  },
})

function App() {
  useForm({
    formControl,
  })

  return (
    <form onSubmit={handleSubmit((data) => console.log(data))}>
      <input {...register("name")} />
      <FormState />
      <ControlledInput />
    </form>
  )
}

function FormState() {
  const { isDirty } = useFormState({
    control, // no longer need context api
  })

  return isDirty ? <p>Form is dirty.</p> : null
}

function ControlledInput() {
  const { field } = useController({
    control, // no longer need context api
    name: "firstName",
  })

  return <input {...field} />
}
```

**Subscribe**

```javascript
const { formControl, register } = createFormControl(props)

formControl.subscribe({
  formState: {
    isDirty: true,
    values: true,
  },
  callback: (formState) => {
    if (formState.isDirty) {
      // do something here
    }

    if (formState.values.test.length > 3) {
      // do something here
    }
  },
})

function App() {
  const { register } = useForm({
    formControl,
  })

  return (
    <form>
      <input {...register("test")} />
    </form>
  )
}
```

### Tips

---

- Use the returned `handleSubmit`, `setValue`, `reset`, and other methods anywhere that can import the control, such as a toolbar button that is outside the form's component tree.
- To sync form values to an external store, call `subscribe` and pick only the state you need. Call the returned function to unsubscribe when you no longer need updates:

  ```javascript
  const unsubscribe = formControl.subscribe({
    formState: { values: true },
    callback: ({ values }) => store.setDraft(values),
  })
  ```

- In tests, you can create a control, render your form with it, and then call methods like `setValue` or `trigger` directly, without simulating every user event.
