Forms
Forms in Swift Rust work the way you'd expect in React, with one twist: server actions let you handle the submission without writing a separate API route.
A simple form
app/contact/page.tsx
import { submitContact } from "./actions";
export default function ContactPage() {
return (
<form action={submitContact}>
<input name="email" type="email" required />
<textarea name="message" required />
<button type="submit">Send</button>
</form>
);
}app/contact/actions.ts
"use server";
import { revalidatePath } from "swift-rust/router";
export async function submitContact(formData: FormData) {
const email = formData.get("email");
const message = formData.get("message");
await db.messages.create({ data: { email, message } });
revalidatePath("/contact");
}Client-side state
For forms that need optimistic updates or progressive enhancement, mark the component with "use client" and use useState + fetch.
usage
"use client";
import { useState } from "react";
export function NewsletterForm() {
const [email, setEmail] = useState("");
const [status, setStatus] = useState<"idle" | "loading" | "done">("idle");
async function onSubmit(e: React.FormEvent) {
e.preventDefault();
setStatus("loading");
await fetch("/api/subscribe", { method: "POST", body: JSON.stringify({ email }) });
setStatus("done");
}
return (
<form onSubmit={onSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<button disabled={status === "loading"}>Subscribe</button>
</form>
);
}Validation
The framework doesn't ship a validation library. We recommend zod for parsing form data and API request bodies.