.claude/skills/react-hook-form/SKILL.md
Form validation and state management for React with TypeScript type safety. Use when: Creating forms, validating user input, handling form submission, implementing multi-step forms, or integrating forms with TanStack Query mutations.
npx skillsauth add kaxuna1/ecomsite react-hook-formInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This codebase uses react-hook-form v7.51.4 with inline validation rules and TypeScript interfaces. Forms integrate with TanStack Query for mutations, i18next for translated error messages, and Framer Motion for animated error displays.
Detected: No zod or @hookform/resolvers in dependencies.
Impact: Validation rules are duplicated between frontend and backend. No runtime type safety.
Recommended: Install zod and @hookform/resolvers/zod for schema-based validation. See the zod skill.
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
interface LoginPayload {
email: string;
password: string;
}
const { register, handleSubmit, formState: { errors } } = useForm<LoginPayload>();
<input
{...register('email', {
required: t('login.emailRequired'),
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: t('login.emailInvalid')
}
})}
/>
{errors.email && <p className="text-red-600">{errors.email.message}</p>}
interface SignupFormData {
password: string;
confirmPassword: string;
}
const { register, watch, formState: { errors } } = useForm<SignupFormData>();
const password = watch('password');
<input
{...register('confirmPassword', {
required: t('signup.confirmPasswordRequired'),
validate: (value) => value === password || t('signup.passwordsNoMatch')
})}
/>
const mutation = useMutation({ mutationFn: createOrder });
const { handleSubmit, formState: { isSubmitting } } = useForm<CheckoutForm>();
const onSubmit = (data: CheckoutForm) => mutation.mutate(data);
<button disabled={mutation.isPending || isSubmitting}>
{mutation.isPending ? 'Submitting...' : 'Submit'}
</button>
| Concept | Usage | Example |
|---------|-------|---------|
| register | Connect input to form | {...register('email', { required: true })} |
| watch | Track field values | const email = watch('email') |
| setValue | Programmatic updates | setValue('email', user.email) |
| formState | Access errors, isDirty, isSubmitting | formState: { errors, isDirty } |
| handleSubmit | Wrap submit handler | onSubmit={handleSubmit(onSubmit)} |
| Pattern | Location | Description |
|---------|----------|-------------|
| Login/Signup | src/pages/LoginPage.tsx, SignupPage.tsx | Auth forms with validation |
| Checkout | src/pages/CheckoutPage.tsx | Multi-field form with address auto-fill |
| Auto-save | src/hooks/useAutoSave.ts | localStorage persistence |
| Unsaved changes | src/hooks/useUnsavedChanges.ts | Browser unload warning |
tools
Zustand lightweight state management with persistence and middleware. Use when: managing client-side state (cart, auth, UI preferences), replacing React Context with simpler API, accessing state outside React components, implementing localStorage persistence
development
Zod schema validation and TypeScript integration for runtime type safety. Use when: Validating API payloads, form inputs, environment variables, or any external data boundaries where TypeScript types alone cannot guarantee safety.
tools
Configures Vite 5.x build tool, dev server, and frontend asset optimization for the Luxia e-commerce platform. Use when: configuring builds, adding environment variables, optimizing bundle size, setting up testing, debugging HMR issues, or adding Vite plugins.
development
Enforces strict TypeScript types across frontend and backend codebases. Use when: Writing new services, DTOs, interfaces, type guards, debugging type errors, or ensuring type safety at API boundaries.