Complete React forms system. PROACTIVELY activate for: (1) Controlled form patterns, (2) React Hook Form setup and validation, (3) Zod schema validation, (4) Dynamic fields with useFieldArray, (5) Server Actions with forms, (6) useOptimistic for optimistic updates, (7) File upload handling, (8) Multi-step form wizards. Provides: Form validation, error handling, field arrays, file drag-drop, form state management. Ensures robust form handling with proper validation and UX.
View on GitHubJosiahSiegel/claude-plugin-marketplace
react-master
January 20, 2026
Select agents to install to:
npx add-skill https://github.com/JosiahSiegel/claude-plugin-marketplace/blob/main/plugins/react-master/skills/react-forms/SKILL.md -a claude-code --skill react-formsInstallation paths:
.claude/skills/react-forms/## Quick Reference
| Approach | Best For | Example |
|----------|----------|---------|
| Controlled | Simple forms | `value={state} onChange={...}` |
| React Hook Form | Complex forms | `useForm()` + `register()` |
| Server Actions | Next.js forms | `action={serverAction}` |
| React Hook Form | Usage |
|-----------------|-------|
| `register` | Connect input | `{...register('name')}` |
| `handleSubmit` | Form submission | `onSubmit={handleSubmit(fn)}` |
| `formState.errors` | Validation errors | `errors.name?.message` |
| `useFieldArray` | Dynamic fields | `fields.map(...)` |
| Validation | Setup |
|------------|-------|
| Inline | `register('email', { required: true })` |
| Zod | `resolver: zodResolver(schema)` |
## When to Use This Skill
Use for **React form implementation**:
- Building controlled forms with validation
- Setting up React Hook Form
- Adding Zod schema validation
- Creating dynamic form fields
- Handling file uploads with preview
- Building multi-step form wizards
- Using Server Actions for form submission
**For state management**: see `react-state-management`
---
# React Forms
## Controlled Forms
### Basic Controlled Form
```tsx
'use client';
import { useState, FormEvent, ChangeEvent } from 'react';
interface FormData {
name: string;
email: string;
message: string;
}
function ContactForm() {
const [formData, setFormData] = useState<FormData>({
name: '',
email: '',
message: '',
});
const handleChange = (
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
console.log('Form submitted:', formData);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name</label>
<input
id="name"
name="name"
type="text"
value={formData.name}