React
Submit forms from React with controlled state and fetch, or use a plain HTML form for zero-JavaScript submissions.
Controlled form with fetch
ContactForm.tsx
import { useState } from "react";
export function ContactForm() {
const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle");
async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setStatus("loading");
const form = e.currentTarget;
const data = Object.fromEntries(new FormData(form));
const res = await fetch("https://formfa.st/f/your_endpoint_id", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(data),
});
if (res.ok) {
setStatus("success");
form.reset();
} else {
setStatus("error");
}
}
if (status === "success") {
return <p>Thanks! We'll be in touch.</p>;
}
return (
<form onSubmit={handleSubmit}>
<input type="text" name="name" placeholder="Name" required />
<input type="email" name="email" placeholder="Email" required />
<textarea name="message" placeholder="Message" />
<input type="hidden" name="_gotcha" style={{ display: "none" }} />
<button type="submit" disabled={status === "loading"}>
{status === "loading" ? "Sending..." : "Send"}
</button>
{status === "error" && <p>Something went wrong. Please try again.</p>}
</form>
);
}JSON vs FormData
Include the
Accept: application/json header to get a JSON response instead of a redirect. This is required for single-page app flows where you want to show a success message inline.Uncontrolled form (no fetch)
For a simpler approach, use a plain HTML form inside React. The browser handles the submission and redirect:
TSX
export function SimpleForm() {
return (
<form action="https://formfa.st/f/your_endpoint_id" method="POST">
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" />
<input type="hidden" name="_gotcha" style={{ display: "none" }} />
<button type="submit">Send</button>
</form>
);
}With client-side validation
You can combine FormFast with any client-side validation library. Here's an example using native validation attributes:
TSX
<form onSubmit={handleSubmit}>
<input
type="text"
name="name"
required
minLength={2}
maxLength={100}
/>
<input
type="email"
name="email"
required
/>
<textarea
name="message"
required
minLength={10}
/>
<button type="submit">Send</button>
</form>You can also configure server-side validation rules in the dashboard for an extra layer of protection.