Zod schema validation and React Hook Form integration for TypeScript frontends. This skill should be used when creating forms, defining API schemas, validating form data, implementing type-safe validation, using ZodResolver with React Hook Form, or migrating legacy forms to the Zod + React Hook Form pattern.
Implements type-safe form validation using Zod schemas with React Hook Form integration in the DTX frontend.
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '~/components/ui/form';
// 1. Define schema
const MySchema = z.object({
email: z.string().email('Invalid email'),
name: z.string().min(2, 'Name too short'),
});
// 2. Create form with zodResolver
const form = useForm<z.infer<typeof MySchema>>({
resolver: zodResolver(MySchema),
defaultValues: { email: '', name: '' },
});
// 3. Handle submission
const onSubmit = (data: z.infer<typeof MySchema>) => {
toast.promise(apiCall(data), {
loading: 'Saving...',
success: 'Saved!',
error: (err) => `Failed: ${err?.response?.data ?? String(err)}`,
});
};
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
Define schemas in ~/components/<feature>/schemas.ts:
UserSchema in ~/components/user/schemas.tsTeamSchema in ~/components/team/schemas.tsGameSchema in ~/components/game/schemas.tsAlways use z.infer<typeof Schema> for types instead of manual interfaces:
export const UserSchema = z.object({ /* ... */ });
export type UserType = z.infer<typeof UserSchema>;
Wrap mutations in toast.promise():
import { toast } from 'sonner';
import { getLogger } from '~/lib/logger';
const log = getLogger('FormComponent');
toast.promise(apiCall(data), {
loading: 'Processing...',
success: (response) => {
setData(response);
return 'Success!';
},
error: (err) => {
log.error('API call failed', err);
return `Failed: ${err?.response?.data ?? String(err)}`;
},
});
For comprehensive documentation:
When migrating legacy forms from manual useState to React Hook Form + Zod:
schemas.tsuseState with useForm({ resolver: zodResolver(Schema) })<FormField> components<Form {...form}> providerReference implementation: ~/pages/profile/profile.tsx
const Schema = z.object({
user: z.object({
name: z.string(),
email: z.string().email(),
}),
});
<FormField control={form.control} name="user.name" ... />
const Schema = z.object({
nickname: z.string().nullable().optional(),
mmr: z.number().min(0).nullable().optional(),
});
<FormField
control={form.control}
name="position"
render={({ field }) => (
<Select onValueChange={(v) => field.onChange(Number(v))} defaultValue={field.value?.toString()}>
{/* options */}
</Select>
)}
/>
Required packages (already installed in DTX frontend):
zod: ^4.1.5react-hook-form: ^7.62.0@hookform/resolvers: ^5.2.1npx skills add kettleofketchup/zod-form-validation下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer