# Formspree React ライブラリ

> Formspree Docs · Reactの使い方 · 2026年1月8日

## インストール

このライブラリは、React がピア依存関係として環境にすでにインストールされていることを前提としています。ヘルパーは [**React Hooks**](https://reactjs.org/docs/hooks-intro.html) を利用しているため、**バージョン 16.8.0 以降が必要です**。

```bash
npm install @formspree/react
```

[**GitHub のソースコード**](https://github.com/formspree/formspree-react) | **[npm パッケージ](https://www.npmjs.com/package/@formspree/react)**  
  
このライブラリは Formspree CLI ありでもなしでも使用できます。この記事ではダッシュボードでフォームを作成することを前提としています。CLI プロジェクトについては、[Formspree CLI](/articles/using-the-cli/the-formspree-cli/) の記事をご覧ください。

## 使い方

`useForm` [**React フック**](https://reactjs.org/docs/hooks-intro.html) は、Formspree で React フォームを設定する最も簡単な方法です。`@formspree/react` をインポートし、Formspree ダッシュボードでフォームを作成して取得したフォームの [hashid](/articles/the-forms-api/getting-your-form-s-hashid/) を引数として `useForm` を呼び出すだけです。

```jsx
import { useForm } from '@formspree/react';

function MyForm() {
  const [state, handleSubmit, reset] = useForm('{your-form-id}');
  if (state.succeeded) {
    return <div>Thank you for signing up!</div>;
  }
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">Email</label>
      <input id="email" type="email" name="email" />
      <button type="submit" disabled={state.submitting}>Sign up</button>
    </form>
  )
}
```

## state オブジェクト

このフックが返す配列の最初の値は state オブジェクトです：

```jsx
const [state, handleSubmit, reset] = useForm('{your-form-id}');
```

state オブジェクトには以下のプロパティが含まれます：

| キー | 説明 |
| --- | --- |
| `submitting` | フォームが現在送信中かどうかを示す真偽値（デフォルトは `false`） |
| `succeeded` | フォームが正常に送信されたかどうかを示す真偽値（デフォルトは `false`） |
| `errors` | サーバーサイドのバリデーションエラーを含む `SubmissionError` クラスのインスタンス（デフォルトは `null`） |
| `result` | 送信が成功したときのリダイレクト URL を持つ `next` プロパティを持つオブジェクト（デフォルトは `null`） |

state は以下のように変化します：

-   `handleSubmit` が呼び出されると、`submitting` が `true` になります
-   送信がサーバーサイドのバリデーションに失敗すると、特定のエラーを含む `errors` の新しいインスタンスが作成されます
-   送信が成功すると、`succeeded` が `true` になり、`result` が `null` でなくなります
-   送信リクエストが完了すると、`submitting` は常に `false` になります

`errors` オブジェクトには以下のメソッドがあります：

| キー | 説明 |
| --- | --- |
| `getFormErrors()` | フォームレベルのエラーの配列を返します |
| `getFieldErrors(field)` | `field` のエラーの配列を返します |
| `getAllFieldErrors()` | すべてのフィールドのフィールドレベルのエラーのキーと値のペアの配列を返します（`[field, errors][]`） |

`errors` オブジェクト内のエラーアイテムには以下のプロパティがあります：

| キー | 説明 |
| --- | --- |
| `message` | 人間が読めるエラーメッセージのフラグメント（例：「is required」） |
| `code` | マシンが読めるエラーコード（下記の[エラーコード](#errorcodes)を参照） |
| `details` | エラーに関するさまざまな追加プロパティを含むオブジェクト。例えば、Stripe と一緒に使用すると、Stripe からの正確なエラーを含む `stripeCode` フィールドが含まれます |

## リセット

フックが返す配列の3番目の値はリセット関数です。

```jsx
const [state, handleSubmit, reset] = useForm('{your-form-id}');
```

この関数は、フォーム送信リクエストが完了した後に state オブジェクトをリセットするために使用します。`result` と `errors` プロパティをクリアし、`submitting` と `succeeded` の真偽値プロパティをデフォルト状態（つまり false）にリセットします。このメソッドを使用して、フォーム送信リクエストが完了した後に表示する「サンキュー」ページで、ユーザーがフォームをリセットして再送信できるようにすることができます。

`reset()` 関数をフォームで使用する方法の例を以下に示します：

```jsx
function TestForm() {
    const [state, submit, reset] = useForm('{your-form-id}');

    if (state.submitting) {
        return <p>Submitting…</p>;
    }

    if (state.succeeded) {
        return (
            <div>
                <p>Thanks!</p>;<button onClick={reset}>Reset</button>
            </div>
        );
    }

    return (
        <div>
            <h1>Form</h1>
            <form onSubmit={submit}>
                <label htmlFor="email">Email</label>
                <input
                    id="email"
                    type="email"
                    name="email"
                    defaultValue="test@example.com"
                />

                <button type="submit">Sign up</button>

            </form>
        </div>
    );
}
```

## バリデーションエラー

`ValidationError` コンポーネントを使用してフィールドエラーを表示するフォームの例を以下に示します：

```jsx
import { ValidationError, useForm } from '@formspree/react';

function MyForm() {
  const [state, handleSubmit] = useForm('{your-form-id}');
  if (state.succeeded) {
    return <div>Thank you for signing up!</div>;
  }
  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="email">Email</label>
      <input id="email" type="email" name="email" required />
      <ValidationError field="email" prefix="Email" errors={state.errors} />
      <button type="submit" disabled={state.submitting}>Sign up</button>
    </form>
  )
}
```

`ValidationError` コンポーネントは以下の特殊なプロパティを受け付けます：

-   `field` — エラーを表示するフィールドの名前。`field` 属性が提供されていない場合は、一般的な（フィールド以外の）エラーが報告されます（下記の[エラーコード](#errorcodes)を参照）
-   `errors` — バリデーションエラーを含むオブジェクト（必須）
-   `prefix` — フィールドの人間が読める名前（オプション、デフォルトは「This field」）

その他の props（`className` など）は `<div>` ラッパーに渡されます。指定したフィールドが無効な場合、このコンポーネントはエラーメッセージを含む `<div>` をレンダリングします：

```jsx
<div {...props}>
  {prefix} {message}
</div>
```

## 追加オプション

このフックは2つの引数を受け付けます：フォームキーとオプションオブジェクトです。

```jsx
const [state, handleSubmit, reset] = useForm('{your-form-key}', options);
```

使用可能なオプションは以下のとおりです：

| キー | 型 | 説明 |
| --- | --- | --- |
| `data` | object | フォームデータにマージする文字列または関数を含むオブジェクト |
| `client` | Formspree | Formspree クライアントのインスタンス |

**使用例**

```jsx
const [state, handleSubmit, reset] = useForm('{your-form-id}', {
  data: {
    subject: 'Someone joined the newsletter',
    pageTitle: function() {
      // This function will be evaluated at submission time
      return document.title;
    }
  }
});
```

## Stripe との連携

Formspree React ライブラリには、Stripe を通じた決済のサポートが含まれています。ライブラリは決済の作成と [Strong Customer Authentication（SCA）](https://stripe.com/docs/strong-customer-authentication)の実行に必要なフロントエンドの状態管理のほとんどを処理します。Formspree のバックエンドは Stripe への決済送信を担当します。Formspree を使用することで、決済フォームの作成に必要な開発工数が大幅に削減されます。

Stripe の機能は遅延読み込みされます。つまり、最小限の Stripe ラッパー（圧縮で約 6k）のみが `@formspree/react` にバンドルされています。Stripe ライブラリの大部分は、Stripe 要素が最初にレンダリングされたときにのみ読み込まれます。

Stripe を使用するには、まずアプリを `FormspreeProvider` コンポーネントでラップし、Stripe の公開可能キーとともに `stripePK` プロパティを含めます。

```jsx
import { FormspreeProvider } from '@formspree/react';

function MyApp() {
  return (
    <FormspreeProvider
      stripePK={'{your-stripe-publishable-key}'}
    >
      <PaymentForm />
    </FormspreeProvider>
  )
}
```

次に、フォームを構築する際は、`@formspree/react` からエクスポートされた `CardElement` コンポーネントを使用します。

```jsx
import { useForm, CardElement, ValidationError } from '@formspree/react';

function PaymentForm() {
  const [state, handleSubmit] = useForm('{your-form-id}');

  if (state.succeeded) {
    return <div>Payment has been handled successfully!</div>;
  }

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="email">Email</label>
        <input id="email" type="email" name="email" />
      </div>
      <div>
        <label>Card details</label>
        <CardElement />
        <ValidationError
          field="paymentMethod"
          errors={state.errors}
        />
      </div>
      <button type="submit" disabled={state.submitting}>
        {state.submitting ? 'Handling payment...' : 'Pay'}
      </button>
    </form>
  )
}
```

`CardElement` コンポーネントは `@stripe/react-stripe-js` から直接渡されます。バージョンの一貫性を確保するためにのみ Formspree React からエクスポートされています。`CardElement` コンポーネントのドキュメントは[こちら](https://stripe.com/docs/payments/accept-card-payments?platform=web&ui=elements&html-or-react=react#add-and-configure-a-component)でご覧いただけます。

`ValidationError` の「paymentMethod」フィールド名に注意してください。これは Stripe から Formspree にデータを送信するためのフィールド名であり、関連する Stripe エラーをキャッチするために `ValidationError` に渡す必要があります。

## 外部フォームライブラリとの連携

`useSubmit` [**React フック**](https://reactjs.org/docs/hooks-intro.html) は、別のフォームライブラリを Formspree と統合する簡単な方法です。`@formspree/react` をインポートし、Formspree ダッシュボードでフォームを作成して取得したフォームの [hashid](/articles/the-forms-api/getting-your-form-s-hashid/) を引数として `useSubmit` を呼び出すだけです。

```tsx
import { useSubmit } from '@formspree/react';
import { useForm } from 'react-hook-form';

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

export function WithReactHookForm() {
  const {
    formState: { errors, isSubmitSuccessful, isSubmitting },
    handleSubmit,
    register,
    setError,
  } = useForm<Inputs>();

  const submit = useSubmit<Inputs>(
    process.env.REACT_APP_REACT_HOOK_FORM_ID as string,
    {
      onError(errs) {
        const formErrs = errs.getFormErrors();
        for (const { code, message } of formErrs) {
          setError(`root.${code}`, {
            type: code,
            message,
          });
        }

        const fieldErrs = errs.getAllFieldErrors();
        for (const [field, errs] of fieldErrs) {
          setError(field, {
            message: errs.map((e) => e.message).join(', '),
          });
        }
      },
    }
  );

  return (
    <div>
      {isSubmitSuccessful ? (
        <h2>Your message has been sent successfully!</h2>
      ) : (
        <form onSubmit={handleSubmit(submit)}>
          <div className="block">
            <label htmlFor="email">Email</label>
            <input {...register('email')} id="email" type="email" />
            {errors.email && <p className="error">{errors.email.message}</p>}
          </div>
          <div className="block">
            <label htmlFor="name">Name</label>
            <input {...register('name')} id="name" />
            {errors.name && <p className="error">{errors.name.message}</p>}
          </div>
          <div className="block">
            <label htmlFor="message">Message</label>
            <textarea {...register('message')} id="message" rows={10} />
          </div>
          {errors.root && (
            <div className="block">
              <ul className="error">
                {Object.values(errors.root).map((err) => {
                  if (typeof err !== 'object') {
                    return <li key={err}>{err}</li>;
                  }
                  const { type, message } = err;
                  return <li key={type}>{message}</li>;
                })}
              </ul>
            </div>
          )}
          <button type="submit" disabled={isSubmitting}>
            {isSubmitting ? 'Submitting...' : 'Submit'}
          </button>
        </form>
      )}
    </div>
  );
}
```

## エラーコード

state オブジェクトの errors 配列に表示される可能性のあるエラーコードは以下のとおりです：

| コード | フィールドエラー | 説明 |
| --- | --- | --- |
| `INACTIVE` |   | フォームが無効化されています |
| `BLOCKED` |   | フォームがブロックされています |
| `EMPTY` |   | データが送信されていません |
| `PROJECT_NOT_FOUND` |   | フォームの送信に無効なプロジェクトキーが使用されました |
| `FORM_NOT_FOUND` |   | フォームの送信に無効なフォーム hashid が使用されました |
| `NO_FILE_UPLOADS` |   | このフォームではファイルアップロードがサポートされていません |
| `TOO_MANY_FILES` |   | フォームに添付ファイルが多すぎます |
| `FILES_TOO_BIG` |   | アップロードされた1つ以上のファイルが最大ファイルサイズを超えています |
| `REQUIRED_FIELD_MISSING` | ✓ | フィールドは必須ですが、値が提供されていません |
| `REQUIRED_FIELD_EMPTY` | ✓ | フィールドは必須ですが、空白または空の文字列が提供されています |
| `TYPE_EMAIL` | ✓ | フィールドにはメールアドレスを含める必要があります |
| `TYPE_NUMERIC` | ✓ | フィールドには数値を含める必要があります |
| `TYPE_TEXT` | ✓ | フィールドにはテキストを含める必要があります |
| `STRIPE_CLIENT_ERROR` | ✓ | Stripe キーがありません |
| `STRIPE_SCA_ERROR` | ✓ | Stripe SCA エラー。`details` を参照してください |
