# Get Started

> Get started with React Hook Form: install the library, register inputs, validate forms, and handle submission in React with minimal code and re-renders.

Source: https://react-hook-form.com/get-started

## Installation

Installing React Hook Form only takes a single command and you're ready to roll.

```bash
npm install react-hook-form
```

## Example

The following code excerpt demonstrates a basic usage example:

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-get-started-ts-5ksmm)

```tsx
import { useForm, SubmitHandler } from "react-hook-form"

type Inputs = {
  example: string
  exampleRequired: 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 its name

  return (
    /* "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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-get-started-j5wxo)

```javascript
import { useForm } from "react-hook-form"

export default function App() {
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm()

  const onSubmit = (data) => console.log(data)

  console.log(watch("example")) // watch input value by passing its name

  return (
    /* "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 Web Video Tutorial

This video tutorial illustrates the basic usage and concepts of React Hook Form.

[Watch on YouTube](https://www.youtube.com/watch?v=RkXv4AXXC_4)

## Register fields

One of the key concepts in React Hook Form is to **`register`** your component into the hook. This will make its value available for both the form validation and submission.

**Note:** Each field is **required** to have a `name` as a key for the registration process.

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-get-started-ts-5ksmm)

```tsx
import { useForm, SubmitHandler } from "react-hook-form"

enum GenderEnum {
  female = "female",
  male = "male",
  other = "other",
}

interface IFormInput {
  firstName: string
  gender: 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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-get-started-j5wxo)

```javascript
import { useForm } from "react-hook-form"

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

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <select {...register("gender")}>
        <option value="female">female</option>
        <option value="male">male</option>
        <option value="other">other</option>
      </select>
      <input type="submit" />
    </form>
  )
}
```

## Apply validation

React Hook Form makes form validation easy by aligning with the existing [HTML standard for form validation](https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation).

List of validation rules supported:

- required
- min
- max
- minLength
- maxLength
- pattern
- validate

You can read more details on each rule in the [register section](https://react-hook-form.com/docs/useform/register).

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-apply-validation-ts-forked-nmbyh)

```tsx
import { useForm, SubmitHandler } from "react-hook-form"

interface IFormInput {
  firstName: string
  lastName: string
  age: 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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-apply-validation-q5m00)

```javascript
import { useForm } from "react-hook-form"

export default function App() {
  const { register, handleSubmit } = useForm()
  const onSubmit = (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>
  )
}
```

## Integrating an existing form

Integrating an existing form is simple. The important step is to register the component's ref and assign the relevant props to your input.

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-adapting-existing-form-ts-uzfxm)

```tsx
import { forwardRef } from "react"
import {
  FieldPath,
  useForm,
  UseFormRegister,
  SubmitHandler,
} from "react-hook-form"

interface IFormValues {
  "First Name": string
  Age: number
}

type InputProps = {
  label: FieldPath<IFormValues>
  register: UseFormRegister<IFormValues>
  required: boolean
}

// The following component is an example of your existing Input Component
const Input = ({ label, register, required }: InputProps) => (
  <>
    <label>{label}</label>
    <input {...register(label, { required })} />
  </>
)

// you can use forwardRef to pass the ref too
const Select = 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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-adapting-existing-form-llbnn)

```javascript
import { forwardRef } from "react"
import { useForm } from "react-hook-form"

// The following component is an example of your existing Input Component
const Input = ({ label, register, required }) => (
  <>
    <label>{label}</label>
    <input {...register(label, { required })} />
  </>
)

// you can use forwardRef to pass the ref too
const Select = forwardRef(({ 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()

  const onSubmit = (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>
  )
}
```

## Integrating with UI libraries

React Hook Form has made it easy to integrate with external UI component libraries. If the component doesn't expose the input's `ref`, then you should use the [Controller](https://react-hook-form.com/docs/usecontroller/controller) component, which will take care of the registration process.

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-with-ui-library-ts-forked-qjgkx)

```tsx
import Select from "react-select"
import { useForm, Controller, SubmitHandler } from "react-hook-form"
import { Input } from "@mui/material"

interface IFormInput {
  firstName: string
  lastName: string
  iceCreamType: { label: string; value: string }
}

const App = () => {
  const { control, handleSubmit } = useForm<IFormInput>({
    defaultValues: {
      firstName: "",
      lastName: "",
      iceCreamType: { label: "", value: "" },
    },
  })

  const onSubmit: SubmitHandler<IFormInput> = (data) => {
    console.log(data)
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="firstName"
        control={control}
        render={({ field }) => <Input {...field} />}
      />
      <Controller
        name="iceCreamType"
        control={control}
        render={({ field }) => (
          <Select
            {...field}
            options={[
              { value: "chocolate", label: "Chocolate" },
              { value: "strawberry", label: "Strawberry" },
              { value: "vanilla", label: "Vanilla" },
            ]}
          />
        )}
      />
      <input type="submit" />
    </form>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-with-ui-library-forked-fp5r3)

```javascript
import Select from "react-select"
import { useForm, Controller } from "react-hook-form"
import { Input } from "@mui/material"

const App = () => {
  const { control, handleSubmit } = useForm({
    defaultValues: {
      firstName: "",
      select: {},
    },
  })
  const onSubmit = (data) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="firstName"
        control={control}
        render={({ field }) => <Input {...field} />}
      />
      <Controller
        name="select"
        control={control}
        render={({ field }) => (
          <Select
            {...field}
            options={[
              { value: "chocolate", label: "Chocolate" },
              { value: "strawberry", label: "Strawberry" },
              { value: "vanilla", label: "Vanilla" },
            ]}
          />
        )}
      />
      <input type="submit" />
    </form>
  )
}
```

## Integrating Controlled Inputs

This library embraces uncontrolled components and native HTML inputs. However, it's hard to avoid working with external controlled components such as [shadcn/ui](https://ui.shadcn.com/docs/components/form), [React-Select](https://github.com/JedWatson/react-select), [AntD](https://github.com/ant-design/ant-design) and [MUI](https://mui.com/). To make this simple, we provide a wrapper component, [Controller](https://react-hook-form.com/docs/usecontroller/controller), to streamline the integration process while still giving you the freedom to use a custom register.

#### Using Component API

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v6-controller-ts-jwyzw)

```tsx
import { useForm, Controller, SubmitHandler } from "react-hook-form"
import { Checkbox } from "@mui/material"

interface IFormInputs {
  MyCheckbox: 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)}>
      <Controller
        name="MyCheckbox"
        control={control}
        rules={{ required: true }}
        render={({ field }) => <Checkbox {...field} />}
      />
      <input type="submit" />
    </form>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-controller-5h1q5)

```javascript
import { useForm, Controller } from "react-hook-form"
import { Checkbox } from "@mui/material"

function App() {
  const { handleSubmit, control, reset } = useForm({
    defaultValues: {
      MyCheckbox: false,
    },
  })
  const onSubmit = (data) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="MyCheckbox"
        control={control}
        rules={{ required: true }}
        render={({ field }) => <Checkbox {...field} />}
      />
      <input type="submit" />
    </form>
  )
}
```

```tsx
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Form, FormControl, FormField } from "@/components/ui/form"
import { Input } from "@/components/ui/input"

const FormSchema = z.object({
  username: z.string().min(2, {
    message: "Username must be at least 2 characters.",
  }),
})

export function InputForm() {
  const form = useForm({
    resolver: zodResolver(FormSchema),
    defaultValues: {
      username: "",
    },
  })

  function onSubmit(data: z.output<typeof FormSchema>) {
    console.log(data)
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="username"
          render={({ field }) => (
            <FormControl>
              <Input {...field} />
            </FormControl>
          )}
        />
        <button type="submit">Submit</button>
      </form>
    </Form>
  )
}
```

**Note:** The `shadcn/ui` example above requires installing `@hookform/resolvers` and `zod`:

```bash
npm install @hookform/resolvers zod
```

If you hit `Cannot find module '@hookform/resolvers/zod'` (or `zod/v4/core`), it's almost always a version mismatch: Zod v4 support requires `@hookform/resolvers` ^3.10 or newer paired with `zod` ^3.25 or `zod` v4, and your `tsconfig.json` needs `"moduleResolution": "bundler"` (or `"node16"`/`"nodenext"`) so the package's subpath exports resolve correctly. See [react-hook-form/resolvers#839](https://github.com/react-hook-form/resolvers/issues/839) for details.

#### Using Hooks API

**TS**

[Open in CodeSandbox](https://codesandbox.io/s/usecontroller-forked-4t8cx)

```tsx
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>
  )
}
```

**JS**

[Open in CodeSandbox](https://codesandbox.io/s/usecontroller-tefsc)

```javascript
import { TextField } from "@mui/material"
import { useController, useForm } from "react-hook-form"

function Input({ control, name }) {
  const {
    field,
    fieldState: { invalid, isTouched, isDirty },
    formState: { touchedFields, dirtyFields },
  } = useController({
    name,
    control,
    rules: { required: true },
  })

  return (
    <TextField
      onChange={field.onChange} // send the value to hook form
      onBlur={field.onBlur} // notify when the input is touched or blurred
      value={field.value} // input value
      name={field.name} // send the input name
      inputRef={field.ref} // send input ref, so we can focus on the input when an error appears
    />
  )
}
```

## Integrating with global state

This library doesn't require you to rely on a state management library, but you can easily integrate with them.

```javascript
import { useForm } from "react-hook-form"
import { connect } from "react-redux"
import updateAction from "./actions"

function App(props) {
  const { register, handleSubmit, setValue } = useForm({
    defaultValues: {
      firstName: "",
      lastName: "",
    },
  })
  // Submit your data into Redux store
  const onSubmit = (data) => props.updateAction(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("firstName")} />
      <input {...register("lastName")} />
      <input type="submit" />
    </form>
  )
}

// Connect your component with redux
export default connect(({ firstName, lastName }) => ({ firstName, lastName }), {
  updateAction,
})(App)
```

## Handle errors

React Hook Form provides an `errors` object to show you the errors in the form. `errors`' type will return given validation constraints. The following example showcases a required validation rule.

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-v7-errormessage-multiple-error-messages-3ur2z)

```javascript
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>
  )
}
```

## Integrating with services

To integrate React Hook Form with a service, you can use the library's built-in submission handling. The `<Form />` component allows you to easily send form data to an API endpoint or other service. [Find out more about the Form component](https://react-hook-form.com/docs/useform/form).

```javascript
import { Form } from "react-hook-form"

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

  return (
    <Form
      action="/api/save" // Send post request with the FormData
      // encType={'application/json'} you can also switch to json object
      onSuccess={() => {
        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>
  )
}
```

## Schema Validation

We also support schema-based form validation, where you can pass your `schema` to [useForm](https://react-hook-form.com/docs/useform) as an optional config. It will validate your input data against the schema and return with either [errors](https://react-hook-form.com/docs/useform/formstate) or a valid result. Supported libraries include:

For complete TypeScript examples with Zod and Yup, see the [React Hook Form integration guides](https://react-hook-form.com/integrations).

<ul style={{ columns: "200px 2", columnGap: "2rem" }}>
  <li>
    <a href="https://github.com/jquense/yup">Yup</a>
  </li>
  <li>
    <a href="https://github.com/colinhacks/zod">Zod</a>
  </li>
  <li>
    <a href="https://github.com/ianstormtaylor/superstruct">Superstruct</a>
  </li>
  <li>
    <a href="https://github.com/sideway/joi">Joi</a>
  </li>
  <li>
    <a href="https://github.com/ealush/vest">Vest</a>
  </li>
  <li>
    <a href="https://github.com/typestack/class-validator">Class Validator</a>
  </li>
  <li>
    <a href="https://github.com/gcanti/io-ts">io-ts</a>
  </li>
  <li>
    <a href="https://github.com/bvego/nope-validator">Nope</a>
  </li>
  <li>
    <a href="https://github.com/neuledge/computed-types">computed-types</a>
  </li>
  <li>
    <a href="https://github.com/arcanis/typanion">typanion</a>
  </li>
  <li>
    <a href="https://github.com/ajv-validator/ajv">Ajv</a>
  </li>
  <li>
    <a href="https://github.com/sinclairzx81/typebox">TypeBox</a>
  </li>
  <li>
    <a href="https://github.com/arktypeio/arktype">ArkType</a>
  </li>
  <li>
    <a href="https://valibot.dev/">Valibot</a>
  </li>
  <li>
    <a href="https://typeschema.com">TypeSchema</a>
  </li>
  <li>
    <a href="https://github.com/Effect-TS/effect">effect-ts</a>
  </li>
  <li>
    <a href="https://github.com/vinejs/vine">VineJS</a>
  </li>
  <li>
    <a href="https://github.com/AlexJPotter/fluentvalidation-ts">
      fluentvalidation-ts
    </a>
  </li>
  <li>
    <a href="https://github.com/nicholasgasior/ata-validator">ata-validator</a>
  </li>
  <li>
    any library that implements{" "}
    <a href="https://standardschema.dev/">Standard Schema</a>
  </li>
</ul>

See the full, up-to-date list in the [`@hookform/resolvers`](https://github.com/react-hook-form/resolvers) repo.

**Step 1:** Install `Yup` into your project.

```bash
npm install @hookform/resolvers yup
```

**Step 2:** Prepare your schema for validation and register inputs with React Hook Form.

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

```javascript
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

You will get the same performance boost and enhancement in React Native. To integrate with input component, you can wrap it with `Controller`.

[Open in Expo Snack](https://snack.expo.io/@bluebill1049/react-hook-form-v7---controller)

```javascript
import { Text, View, TextInput, Button } 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>
      <Controller
        control={control}
        rules={{
          required: true,
        }}
        render={({ field: { onChange, onBlur, value } }) => (
          <TextInput
            placeholder="First name"
            onBlur={onBlur}
            onChangeText={onChange}
            value={value}
          />
        )}
        name="firstName"
      />
      {errors.firstName && <Text>This is required.</Text>}

      <Controller
        control={control}
        rules={{
          maxLength: 100,
        }}
        render={({ field: { onChange, onBlur, value } }) => (
          <TextInput
            placeholder="Last name"
            onBlur={onBlur}
            onChangeText={onChange}
            value={value}
          />
        )}
        name="lastName"
      />

      <Button title="Submit" onPress={handleSubmit(onSubmit)} />
    </View>
  )
}
```

## TypeScript

React Hook Form is built with `TypeScript`, and you can define a `FormData` type to support form values.

[Open in CodeSandbox](https://codesandbox.io/s/react-hook-form-typescript-qwk7b)

```tsx
import { useForm } from "react-hook-form"

type FormData = {
  firstName: string
  lastName: 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 type

  return (
    <form onSubmit={onSubmit}>
      <label>First Name</label>
      <input {...register("firstName")} />
      <label>Last Name</label>
      <input {...register("lastName")} />
      <button
        type="button"
        onClick={() => {
          setValue("lastName", "luo") // ✅
          setValue("firstName", true) // ❌: true is not string
          errors.bill // ❌: property bill does not exist
        }}
      >
        SetValue
      </button>
    </form>
  )
}
```

## Design and philosophy

React Hook Form's design and philosophy focus on user and developer experience. The library aims to provide users with a smoother interaction experience by fine-tuning the performance and improving accessibility. Some of the performance enhancements include:

- Introducing form state subscription model through the proxy
- Avoiding unnecessary computation
- Isolating component re-rendering when required

Overall, it improves the user experience as users interact with the application. For developers, we introduced built-in validation and are closely aligned with HTML standards, allowing further extension with powerful validation methods and native integration with schema validation. In addition, having a strongly type-checked form with the help of TypeScript provides early build-time feedback to help and guide developers in building a robust form solution.

The following talk given by [Bill](https://twitter.com/bluebill1049) showcased some of the ideas and design patterns:

[Watch on YouTube](https://www.youtube.com/watch?v=ZFxHdpzaEmM)
