AgentSkillsCN

react-hook-form

利用 TypeScript 类型安全特性,为 React 表单提供强大的校验与状态管理能力。 适用场景:创建表单、校验用户输入、处理表单提交、实现多步骤表单,或将表单与 TanStack Query 的突变操作无缝集成时使用。

SKILL.md
--- frontmatter
name: react-hook-form
description: |
  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.
allowed-tools: Read, Edit, Write, Glob, Grep, Bash

React Hook Form Skill

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.

WARNING: Missing Zod Integration

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.

Quick Start

Basic Form with Validation

typescript
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>}

Form with Cross-Field Validation

typescript
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')
  })}
/>

Form with TanStack Query Mutation

typescript
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>

Key Concepts

ConceptUsageExample
registerConnect input to form{...register('email', { required: true })}
watchTrack field valuesconst email = watch('email')
setValueProgrammatic updatessetValue('email', user.email)
formStateAccess errors, isDirty, isSubmittingformState: { errors, isDirty }
handleSubmitWrap submit handleronSubmit={handleSubmit(onSubmit)}

Project Patterns

PatternLocationDescription
Login/Signupsrc/pages/LoginPage.tsx, SignupPage.tsxAuth forms with validation
Checkoutsrc/pages/CheckoutPage.tsxMulti-field form with address auto-fill
Auto-savesrc/hooks/useAutoSave.tslocalStorage persistence
Unsaved changessrc/hooks/useUnsavedChanges.tsBrowser unload warning

See Also

Related Skills

  • typescript - Type-safe form interfaces
  • tanstack-query - Mutation integration
  • zod - Schema validation (recommended)
  • tailwind - Form styling
  • react - Component patterns