Form ID

React

대기, 오류, 성공 상태와 필드 오류, 선택적인 사람 확인을 갖춘 React 폼.

Vite, Remix, React Router, Gatsby, Next.js 클라이언트 컴포넌트 등 어떤 React 앱에서든 작동합니다. 브라우저에서 바로 POST하므로 방문자마다 각자의 레이트 리밋이 적용됩니다.

SDK 설치

Terminal
npm install @ikiform/sdk

완성된 폼

contact-form.jsx
import { challenge, submit } from "@ikiform/sdk";
import { useState } from "react";

const FORM_ID = "frm_xxxxxxxxxxxxxxxx";

export function ContactForm({ humanCheck = false }) {
  const [status, setStatus] = useState("idle");
  const [errors, setErrors] = useState({});
  const [message, setMessage] = useState("");

  async function onSubmit(event) {
    event.preventDefault();
    const data = new FormData(event.currentTarget);
    setStatus("sending");
    setErrors({});
    try {
      const turnstileToken = humanCheck ? await challenge(FORM_ID) : undefined;
      const result = await submit(FORM_ID, data, { turnstileToken });
      if (result.ok) return setStatus("sent");
      setErrors(result.error.fields ?? {});
      setMessage(result.error.message);
    } catch {
      setMessage("The human check didn't finish. Try again.");
    }
    setStatus("error");
  }

  if (status === "sent") return <p>Thanks, we got it.</p>;

  return (
    <form onSubmit={onSubmit}>
      <label>
        Email
        <input name="email" type="email" required />
      </label>
      {errors.email ? <p>{errors.email[0]}</p> : null}
      <label>
        Message
        <textarea name="message" />
      </label>
      {errors.message ? <p>{errors.message[0]}</p> : null}
      <input name="_gotcha" type="text" tabIndex={-1} autoComplete="off" hidden />
      {status === "error" && message ? <p role="alert">{message}</p> : null}
      <button disabled={status === "sending"}>Send</button>
    </form>
  );
}
  • 폼의 스팸 검사가 Ikiform으로 설정되어 있으면 humanCheck를 전달하세요. 확인이 꺼져 있으면 생략하세요.
  • 확인이 실패하거나 중단되면 challenge가 ChallengeError로 reject되고, catch가 이를 메시지로 바꿉니다.
  • SDK 없이 쓰려면 JavaScript와 fetch처럼 submit을 fetch로 바꾸세요.

폼 액션으로 사용

React 19에서는 submit이 반환하는 값이 폼 액션 타입도 만족하므로 action에 바로 전달할 수 있습니다. React 내부의 $ACTION_ 필드는 전송 전에 제거됩니다.

newsletter.jsx
import { submit } from "@ikiform/sdk";

export function Newsletter() {
  return (
    <form action={(data) => submit("frm_xxxxxxxxxxxxxxxx", data)}>
      <input name="email" type="email" required />
      <button>Subscribe</button>
    </form>
  );
}

보내기 전에 검증

validate는 12가지 필드 타입 모두에 서버와 같은 규칙과 메시지를 사용하므로, 요청 전에 오류를 보여 줄 수 있습니다. 최종 판단은 여전히 서버가 합니다.

validate.js
import { getSchema, validate } from "@ikiform/sdk";

const schema = await getSchema("frm_xxxxxxxxxxxxxxxx");

function check(form) {
  if (!schema.ok) return {};
  return validate(schema.schema.fields, new FormData(form));
}