> ## 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 (Vanilla)

> Submit to Formbase from any React component.

React works well with Formbase because you can choose between native form posts or programmatic submissions. Use native posts for the simplest setup, and use fetch when you need full UI control.

The examples below use fetch with `redirect: 'manual'` to avoid following the Formbase redirect in the browser.

<Steps>
  <Step title="Create your form UI">
    Build the form as usual and give each input a `name` attribute.
  </Step>

  <Step title="Submit to Formbase">
    <Tabs>
      <Tab title="Basic submission">
        ```tsx theme={null}
        import { useState } from 'react';

        export default function ContactForm() {
          const [status, setStatus] = useState('');
          const [isSubmitting, setIsSubmitting] = useState(false);

          const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
            event.preventDefault();
            setStatus('');
            setIsSubmitting(true);

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

            if (response.status === 303 || response.ok) {
              setStatus('Submitted!');
              event.currentTarget.reset();
            } else {
              setStatus('Submission failed.');
            }

            setIsSubmitting(false);
          };

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

        The `FormData` API serializes the form exactly like a normal browser post.
      </Tab>

      <Tab title="File upload">
        ```tsx theme={null}
        import { useState } from 'react';

        export default function UploadForm() {
          const [status, setStatus] = useState('');

          const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
            event.preventDefault();

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

            setStatus(response.status === 303 || response.ok ? 'Uploaded!' : 'Failed');
          };

          return (
            <form onSubmit={handleSubmit} encType="multipart/form-data">
              <input name="resume" type="file" />
              <button type="submit">Upload</button>
              {status && <p>{status}</p>}
            </form>
          );
        }
        ```

        Add `encType="multipart/form-data"` when your form includes file inputs.
      </Tab>
    </Tabs>
  </Step>
</Steps>

<Callout type="note">
  Browser submissions return a `303` redirect. Treat that as success in client-side code, or post from your server for a JSON response.
</Callout>
