Formspree React ライブラリ
インストール
このライブラリは、React がピア依存関係として環境にすでにインストールされていることを前提としています。ヘルパーは React Hooks を利用しているため、バージョン 16.8.0 以降が必要です。
npm install @formspree/react
このライブラリは Formspree CLI ありでもなしでも使用できます。この記事ではダッシュボードでフォームを作成することを前提としています。CLI プロジェクトについては、Formspree CLI の記事をご覧ください。
使い方
useForm React フック は、Formspree で React フォームを設定する最も簡単な方法です。@formspree/react をインポートし、Formspree ダッシュボードでフォームを作成して取得したフォームの hashid を引数として useForm を呼び出すだけです。
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 オブジェクトです:
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 | マシンが読めるエラーコード(下記のエラーコードを参照) |
details | エラーに関するさまざまな追加プロパティを含むオブジェクト。例えば、Stripe と一緒に使用すると、Stripe からの正確なエラーを含む stripeCode フィールドが含まれます |
リセット
フックが返す配列の3番目の値はリセット関数です。
const [state, handleSubmit, reset] = useForm('{your-form-id}');
この関数は、フォーム送信リクエストが完了した後に state オブジェクトをリセットするために使用します。result と errors プロパティをクリアし、submitting と succeeded の真偽値プロパティをデフォルト状態(つまり false)にリセットします。このメソッドを使用して、フォーム送信リクエストが完了した後に表示する「サンキュー」ページで、ユーザーがフォームをリセットして再送信できるようにすることができます。
reset() 関数をフォームで使用する方法の例を以下に示します:
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 コンポーネントを使用してフィールドエラーを表示するフォームの例を以下に示します:
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属性が提供されていない場合は、一般的な(フィールド以外の)エラーが報告されます(下記のエラーコードを参照)errors— バリデーションエラーを含むオブジェクト(必須)prefix— フィールドの人間が読める名前(オプション、デフォルトは「This field」)
その他の props(className など)は <div> ラッパーに渡されます。指定したフィールドが無効な場合、このコンポーネントはエラーメッセージを含む <div> をレンダリングします:
<div {...props}>
{prefix} {message}
</div>
追加オプション
このフックは2つの引数を受け付けます:フォームキーとオプションオブジェクトです。
const [state, handleSubmit, reset] = useForm('{your-form-key}', options);
使用可能なオプションは以下のとおりです:
| キー | 型 | 説明 |
|---|---|---|
data | object | フォームデータにマージする文字列または関数を含むオブジェクト |
client | Formspree | Formspree クライアントのインスタンス |
使用例
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)の実行に必要なフロントエンドの状態管理のほとんどを処理します。Formspree のバックエンドは Stripe への決済送信を担当します。Formspree を使用することで、決済フォームの作成に必要な開発工数が大幅に削減されます。
Stripe の機能は遅延読み込みされます。つまり、最小限の Stripe ラッパー(圧縮で約 6k)のみが @formspree/react にバンドルされています。Stripe ライブラリの大部分は、Stripe 要素が最初にレンダリングされたときにのみ読み込まれます。
Stripe を使用するには、まずアプリを FormspreeProvider コンポーネントでラップし、Stripe の公開可能キーとともに stripePK プロパティを含めます。
import { FormspreeProvider } from '@formspree/react';
function MyApp() {
return (
<FormspreeProvider
stripePK={'{your-stripe-publishable-key}'}
>
<PaymentForm />
</FormspreeProvider>
)
}
次に、フォームを構築する際は、@formspree/react からエクスポートされた CardElement コンポーネントを使用します。
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 コンポーネントのドキュメントはこちらでご覧いただけます。
ValidationError の「paymentMethod」フィールド名に注意してください。これは Stripe から Formspree にデータを送信するためのフィールド名であり、関連する Stripe エラーをキャッチするために ValidationError に渡す必要があります。
外部フォームライブラリとの連携
useSubmit React フック は、別のフォームライブラリを Formspree と統合する簡単な方法です。@formspree/react をインポートし、Formspree ダッシュボードでフォームを作成して取得したフォームの hashid を引数として useSubmit を呼び出すだけです。
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 を参照してください |