API 경로를 사용하여 양식 작성
HTML 양식을 사용하면 브라우저가 페이지를 새로 고치거나 새 페이지로 이동합니다. 대신 양식 데이터를 API 엔드포인트로 보내려면 JavaScript를 사용하여 양식 제출을 가로채야 합니다.
이 레시피는 양식 데이터를 API 엔드포인트로 보내고 해당 데이터를 처리하는 방법을 보여줍니다.
전제 조건
섹션 제목: 전제 조건- SSR (
output: 'server'
또는'hybrid'
)가 활성화된 프로젝트가 필요합니다. - 설치된 UI 프레임워크 통합이 필요합니다.
레시피
섹션 제목: 레시피-
양식 데이터를 수신할
/api/feedback
에POST
API 엔드포인트를 생성합니다. 처리하려면request.formData()
를 사용하세요. 사용하기 전에 양식 값의 유효성을 검사하세요.이 예시에서는 메시지와 함께 JSON 객체를 클라이언트에 다시 보냅니다.
src/pages/api/feedback.ts 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 });}; -
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>);}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>);}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>);}src/components/FeedbackForm.svelte <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>src/components/FeedbackForm.vue <template><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></template> -
제출 이벤트를 받아들이는 함수를 만든 다음 이를
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>);}src/components/FeedbackForm.tsx import { FormEvent, useState } from "react";export default function Form() {const [responseMessage, setResponseMessage] = useState("");async function submit(e: FormEvent<HTMLFormElement>) {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 htmlFor="name">Name<input type="text" id="name" name="name" autoComplete="name" required /></label><label htmlFor="email">Email<input type="email" id="email" name="email" autoComplete="email" required /></label><label htmlFor="message">Message<textarea id="message" name="message" autoComplete="off" required /></label><button>Send</button>{responseMessage && <p>{responseMessage}</p>}</form>);}src/components/FeedbackForm.tsx import { createSignal, createResource, Suspense } from "solid-js";async function postFormData(formData: FormData) {const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();return data;}export default function Form() {const [formData, setFormData] = createSignal<FormData>();const [response] = createResource(formData, postFormData);function submit(e: SubmitEvent) {e.preventDefault();setFormData(new FormData(e.target as HTMLFormElement));}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><Suspense>{response() && <p>{response().message}</p>}</Suspense></form>);}src/components/FeedbackForm.svelte <script lang="ts">let responseMessage: string;async function submit(e: SubmitEvent) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage = data.message;}</script><form on:submit={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>{#if responseMessage}<p>{responseMessage}</p>{/if}</form>src/components/FeedbackForm.vue <script setup lang="ts">import { ref } from "vue";const responseMessage = ref<string>();async function submit(e: Event) {e.preventDefault();const formData = new FormData(e.currentTarget as HTMLFormElement);const response = await fetch("/api/feedback", {method: "POST",body: formData,});const data = await response.json();responseMessage.value = data.message;}</script><template><form @submit="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><p v-if="responseMessage">{{ responseMessage }}</p></form></template> - 이벤트에서
-
<FeedbackForm />
컴포넌트를 가져와 페이지에 포함합니다. 양식 로직이 원할 때 수화되도록 하려면client:*
지시어를 사용하세요.src/pages/index.astro ---import FeedbackForm from "../components/FeedbackForm"---<FeedbackForm client:load />src/pages/index.astro ---import FeedbackForm from "../components/FeedbackForm"---<FeedbackForm client:load />src/pages/index.astro ---import FeedbackForm from "../components/FeedbackForm"---<FeedbackForm client:load />src/pages/index.astro ---import FeedbackForm from "../components/FeedbackForm.svelte"---<FeedbackForm client:load />src/pages/index.astro ---import FeedbackForm from "../components/FeedbackForm.vue"---<FeedbackForm client:load />