> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formbase.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# React Hook Form

> Connect React Hook Form submissions to Formbase.

React Hook Form gives you structured values and validation hooks. You can submit those values directly to Formbase as JSON, or switch to `FormData` when you need file uploads.

These examples use client-side fetch. If you prefer a JSON response from Formbase, submit from a server action or API route.

<Steps>
  <Step title="Create your form">
    Register fields as usual with `useForm`.
  </Step>

  <Step title="Submit to Formbase">
    <Tabs>
      <Tab title="JSON submission">
        ```tsx theme={null}
        import { useForm } from 'react-hook-form';

        type FormValues = {
          name: string;
          email: string;
          message: string;
        };

        export default function ContactForm() {
          const { register, handleSubmit, formState: { isSubmitting } } = useForm<FormValues>();

          const onSubmit = async (data: FormValues) => {
            const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify(data),
              redirect: 'manual',
            });

            if (response.status !== 303 && !response.ok) {
              throw new Error('Submission failed');
            }
          };

          return (
            <form onSubmit={handleSubmit(onSubmit)}>
              <input {...register('name')} placeholder="Name" required />
              <input {...register('email')} type="email" placeholder="Email" required />
              <textarea {...register('message')} required />
              <button type="submit" disabled={isSubmitting}>
                {isSubmitting ? 'Sending...' : 'Send'}
              </button>
            </form>
          );
        }
        ```

        JSON is great when you want structured data or arrays.
      </Tab>

      <Tab title="File uploads">
        ```tsx theme={null}
        import { useForm } from 'react-hook-form';

        type UploadValues = {
          name: string;
          resume: FileList;
        };

        export default function UploadForm() {
          const { register, handleSubmit, formState: { isSubmitting } } = useForm<UploadValues>();

          const onSubmit = async (data: UploadValues) => {
            const formData = new FormData();
            formData.append('name', data.name);
            formData.append('resume', data.resume[0]);

            const response = await fetch('https://formbase.dev/s/YOUR_FORM_ID', {
              method: 'POST',
              body: formData,
              redirect: 'manual',
            });

            if (response.status !== 303 && !response.ok) {
              throw new Error('Upload failed');
            }
          };

          return (
            <form onSubmit={handleSubmit(onSubmit)} encType="multipart/form-data">
              <input {...register('name')} placeholder="Name" required />
              <input {...register('resume')} type="file" />
              <button type="submit" disabled={isSubmitting}>
                {isSubmitting ? 'Uploading...' : 'Upload'}
              </button>
            </form>
          );
        }
        ```

        Use `FormData` when files are involved.
      </Tab>
    </Tabs>
  </Step>
</Steps>

<Callout type="note">
  Client submissions get a `303` redirect response. Treat `303` as success or submit from a server action for JSON.
</Callout>
