new-form
Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Generate a semver-compliant release note from git history; on user confirmation, bump version, update CHANGELOG, create git tag, and publish a GitHub Release with gh
Scaffold a new backend server action with auth check, Zod input validation, repository call, and error handling
Scaffold a typed React client component with props interface, Tailwind styling, and shadcn/ui primitives
Create a Zod input schema file in src/backend/services/inputs/ for a domain entity
Scaffold a Next.js App Router page with optional server-side session check, metadata, and layout
Scaffold TanStack Query useQuery and/or useMutation hooks for a feature, calling a backend server action
| name | new-form |
| description | Scaffold a React Hook Form with Zod validation, useMutation, and toast notifications |
Create a form component using React Hook Form + Zod + TanStack Query mutation in techdiary.dev.
"use client" at the topzodResolver from @hookform/resolvers/zodsrc/backend/services/inputs/<domain>.input.ts — do not duplicate schema definitionsfilterUndefined() for default values to avoid uncontrolled→controlled warningsSubmitHandler<z.infer<typeof Schema>>useMutation, never call it directly in onSubmitForm, FormField, FormItem, FormLabel, FormControl, FormMessage"use client";
import { useForm, SubmitHandler } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation } from "@tanstack/react-query";
import { toast } from "sonner";
import { z } from "zod";
import {
Form, FormControl, FormField, FormItem, FormLabel, FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import * as <domain>Actions from "@/backend/services/<domain>.action";
import { <Domain>Input } from "@/backend/services/inputs/<domain>.input";
import { filterUndefined } from "@/lib/utils";
type FormValues = z.infer<typeof <Domain>Input.<schemaName>>;
interface Props {
// initial data if editing
}
export const <Name>Form: React.FC<Props> = ({ /* props */ }) => {
const form = useForm<FormValues>({
defaultValues: filterUndefined({
field: "",
}),
resolver: zodResolver(<Domain>Input.<schemaName>),
});
const mutation = useMutation({
mutationFn: (payload: FormValues) => <domain>Actions.<actionName>(payload),
onSuccess: () => {
toast("Saved successfully");
form.reset();
},
onError: (error) => {
toast.error(error.message ?? "Something went wrong");
},
});
const onSubmit: SubmitHandler<FormValues> = (payload) => {
mutation.mutate(payload);
};
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="field"
render={({ field }) => (
<FormItem>
<FormLabel>Label</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" disabled={mutation.isPending}>
{mutation.isPending ? "Saving..." : "Save"}
</Button>
</form>
</Form>
);
};