コンテンツにスキップ

APIルートでフォームを構築する

HTMLフォームはページを再読み込みしたり、別ページへ遷移したりします。代わりにAPIエンドポイントへフォームデータを送信するには、JavaScriptでフォーム送信をインターセプトする必要があります。

このレシピでは、フォームデータをAPIエンドポイントへ送信し、そのデータを処理する方法を説明します。

  1. フォームデータを受け取るPOSTのAPIエンドポイント/api/feedbackを作成します。request.formData()で処理します。使用前に必ず値を検証します。

    この例ではメッセージを含むJSONオブジェクトをクライアントへ返します。

    src/pages/api/feedback.ts
    export const prerender = false; // 「server」モードでは不要です
    import type { APIRoute } from "astro";
    export const POST: APIRoute = async ({ request }) => {
    const data = await request.formData();
    const name = data.get("name");
    const email = data.get("email");
    const message = data.get("message");
    // データのバリデーション — 実際にはこれ以上の検証を行う必要がある場合が多いです
    if (!name || !email || !message) {
    return new Response(
    JSON.stringify({
    message: "Missing required fields",
    }),
    { status: 400 }
    );
    }
    // データを処理して、成功レスポンスを返す
    return new Response(
    JSON.stringify({
    message: "Success!"
    }),
    { status: 200 }
    );
    };
  2. 使用中のUIフレームワークでフォームコンポーネントを作成します。各入力には、その値の意味を表すname属性を付けます。

    必ず送信用の<button>または<input type="submit">要素を含めます。

    src/components/FeedbackForm.tsx
    export default function Form() {
    return (
    <form>
    <label>
    Name
    <input type="text" id="name" name="name" required />
    </label>
    <label>
    Email
    <input type="email" id="email" name="email" required />
    </label>
    <label>
    Message
    <textarea id="message" name="message" required />
    </label>
    <button>Send</button>
    </form>
    );
    }
  3. 送信イベントを受け取る関数を作成し、フォームのsubmitハンドラーとして渡します。

    関数内では次を行います。

    • ブラウザーの既定の送信処理を上書きするためにpreventDefault()を呼びます。

    • FormDataオブジェクトを作成し、fetch()POSTリクエストとしてエンドポイントへ送ります。

    src/components/FeedbackForm.tsx
    import { useState } from "preact/hooks";
    export default function Form() {
    const [responseMessage, setResponseMessage] = useState("");
    async function submit(e: SubmitEvent) {
    e.preventDefault();
    const formData = new FormData(e.target as HTMLFormElement);
    const response = await fetch("/api/feedback", {
    method: "POST",
    body: formData,
    });
    const data = await response.json();
    if (data.message) {
    setResponseMessage(data.message);
    }
    }
    return (
    <form onSubmit={submit}>
    <label>
    Name
    <input type="text" id="name" name="name" required />
    </label>
    <label>
    Email
    <input type="email" id="email" name="email" required />
    </label>
    <label>
    Message
    <textarea id="message" name="message" required />
    </label>
    <button>Send</button>
    {responseMessage && <p>{responseMessage}</p>}
    </form>
    );
    }
  4. ページで<FeedbackForm />コンポーネントをインポートして配置します。必要なタイミングでロジックをハイドレートするため、必ずclient:*ディレクティブを使います。

    src/pages/index.astro
    ---
    import FeedbackForm from "../components/FeedbackForm"
    ---
    <FeedbackForm client:load />
貢献する コミュニティ スポンサー