AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Form React

skill-bbeierle12-skill-mcp-claude-form-react · by Bbeierle12

Production-ready React form patterns using React Hook Form (default) and TanStack Form with Zod integration. Use when building forms in React applications. Implements reward-early-punish-late validation timing.

No reviews yet
0 installs
35 views
0.0% view→install

Install

$ agentstack add skill-bbeierle12-skill-mcp-claude-form-react

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-bbeierle12-skill-mcp-claude-form-react)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Form React? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Form React

Production React form patterns. Default stack: React Hook Form + Zod.

Quick Start

npm install react-hook-form @hookform/resolvers zod
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';

// 1. Define schema
const schema = z.object({
  email: z.string().email('Invalid email'),
  password: z.string().min(8, 'Min 8 characters')
});

type FormData = z.infer;

// 2. Use form
function LoginForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
    mode: 'onBlur' // Reward early, punish late
  });

  return (
     console.log(data))}>
      
      {errors.email && {errors.email.message}}
      
      
      {errors.password && {errors.password.message}}
      
      Sign in
    
  );
}

When to Use Which

| Criteria | React Hook Form | TanStack Form | |----------|-----------------|---------------| | Performance | ✅ Best (uncontrolled) | Good (controlled) | | Bundle size | 12KB | ~15KB | | TypeScript | Good | ✅ Excellent | | Cross-framework | ❌ React only | ✅ Multi-framework | | React Native | Requires workarounds | ✅ Native support | | Built-in async validation | Manual | ✅ Built-in debouncing | | Ecosystem | ✅ Mature (4+ years) | Growing |

Default: React Hook Form — Better performance for most React web apps.

Use TanStack Form when:

  • Building cross-framework component libraries
  • Need strict controlled component behavior
  • Heavy async validation (username checks)
  • React Native applications

React Hook Form Patterns

Basic Form

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { loginSchema, type LoginFormData } from './schemas';

export function LoginForm({ onSubmit }: { onSubmit: (data: LoginFormData) => void }) {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting, touchedFields }
  } = useForm({
    resolver: zodResolver(loginSchema),
    mode: 'onBlur',           // First validation on blur (punish late)
    reValidateMode: 'onChange' // Re-validate on change (real-time correction)
  });

  return (
    
      
        Email
        
        {touchedFields.email && errors.email && (
          {errors.email.message}
        )}
      

      
        Password
        
        {touchedFields.password && errors.password && (
          {errors.password.message}
        )}
      

      
        {isSubmitting ? 'Signing in...' : 'Sign in'}
      
    
  );
}

Reusable Form Field Component

// FormField.tsx
import { useFormContext } from 'react-hook-form';
import { ReactNode } from 'react';

interface FormFieldProps {
  name: string;
  label: string;
  type?: string;
  autoComplete?: string;
  hint?: string;
  required?: boolean;
  children?: ReactNode;
}

export function FormField({
  name,
  label,
  type = 'text',
  autoComplete,
  hint,
  required,
  children
}: FormFieldProps) {
  const {
    register,
    formState: { errors, touchedFields }
  } = useFormContext();

  const error = errors[name];
  const touched = touchedFields[name];
  const showError = touched && error;
  const showValid = touched && !error;

  return (
    
      
        {label}
        {required && *}
      
      
      {hint && {hint}}
      
      {children || (
        
      )}
      
      {showError && (
        
          {error.message as string}
        
      )}
    
  );
}

Using FormProvider for Nested Components

// Form wrapper
import { FormProvider, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

export function CheckoutForm() {
  const methods = useForm({
    resolver: zodResolver(checkoutSchema),
    mode: 'onBlur'
  });

  return (
    
      
        
        
        
        Place Order
      
    
  );
}

// Nested section component
function ContactSection() {
  return (
    
      Contact Information
      
      
    
  );
}

Watching Values (Real-time)

import { useForm, useWatch } from 'react-hook-form';

function RegistrationForm() {
  const { register, control } = useForm();
  
  // Watch password for strength meter
  const password = useWatch({ control, name: 'password', defaultValue: '' });
  
  return (
    
      
      
    
  );
}

Conditional Fields

import { useFormContext, useWatch } from 'react-hook-form';

function ConditionalField({ watchField, condition, children }) {
  const { control } = useFormContext();
  const value = useWatch({ control, name: watchField });
  
  if (!condition(value)) return null;
  return <>{children};
}

// Usage
 val === true}>
  

Async Validation (Username Check)

import { useForm } from 'react-hook-form';

function RegistrationForm() {
  const { register, setError, clearErrors } = useForm();
  
  const checkUsername = async (username: string) => {
    if (username.length  checkUsername(e.target.value)}
    />
  );
}

Form Reset

function EditProfileForm({ defaultValues }) {
  const { reset, handleSubmit } = useForm({ defaultValues });
  
  // Reset to new values
  useEffect(() => {
    reset(defaultValues);
  }, [defaultValues, reset]);
  
  // Reset to initial values
  const handleCancel = () => reset();
  
  return (
    
      {/* fields */}
      Cancel
      Save
    
  );
}

Array Fields (Dynamic)

import { useFieldArray, useForm } from 'react-hook-form';

function TeamMembersForm() {
  const { control, register } = useForm({
    defaultValues: {
      members: [{ name: '', email: '' }]
    }
  });
  
  const { fields, append, remove } = useFieldArray({
    control,
    name: 'members'
  });

  return (
    
      {fields.map((field, index) => (
        
          
          
           remove(index)}>Remove
        
      ))}
      
       append({ name: '', email: '' })}>
        Add Member
      
    
  );
}

TanStack Form Patterns

Basic Form

import { useForm } from '@tanstack/react-form';
import { zodValidator } from '@tanstack/zod-form-adapter';
import { loginSchema } from './schemas';

function LoginForm() {
  const form = useForm({
    defaultValues: {
      email: '',
      password: ''
    },
    onSubmit: async ({ value }) => {
      await login(value);
    },
    validatorAdapter: zodValidator()
  });

  return (
     {
        e.preventDefault();
        e.stopPropagation();
        form.handleSubmit();
      }}
    >
      
        {(field) => (
          
            Email
             field.handleChange(e.target.value)}
              onBlur={field.handleBlur}
            />
            {field.state.meta.isTouched && field.state.meta.errors.length > 0 && (
              {field.state.meta.errors[0]}
            )}
          
        )}
      

      
        {(field) => (
          
            Password
             field.handleChange(e.target.value)}
              onBlur={field.handleBlur}
            />
            {field.state.meta.isTouched && field.state.meta.errors.length > 0 && (
              {field.state.meta.errors[0]}
            )}
          
        )}
      

       [state.canSubmit, state.isSubmitting]}>
        {([canSubmit, isSubmitting]) => (
          
            {isSubmitting ? 'Signing in...' : 'Sign in'}
          
        )}
      
    
  );
}

Async Validation with Debouncing

 {
      const response = await fetch(`/api/check-username?u=${value}`);
      const { available } = await response.json();
      return available ? undefined : 'Username is taken';
    }
  }}
>
  {(field) => (
    
       field.handleChange(e.target.value)}
        onBlur={field.handleBlur}
      />
      {field.state.meta.isValidating && Checking...}
      {field.state.meta.errors[0] && {field.state.meta.errors[0]}}
    
  )}

Linked Fields (Password Confirmation)

 {
      const password = fieldApi.form.getFieldValue('password');
      return value !== password ? 'Passwords do not match' : undefined;
    }
  }}
>
  {(field) => (
     field.handleChange(e.target.value)}
    />
  )}

Common Patterns

Form with Server Errors

function LoginForm() {
  const [serverError, setServerError] = useState(null);
  
  const { handleSubmit, setError } = useForm({
    resolver: zodResolver(loginSchema)
  });

  const onSubmit = async (data: LoginFormData) => {
    try {
      setServerError(null);
      await login(data);
    } catch (error) {
      if (error.field) {
        // Field-specific error
        setError(error.field, { message: error.message });
      } else {
        // General error
        setServerError(error.message);
      }
    }
  };

  return (
    
      {serverError && (
        
          {serverError}
        
      )}
      {/* fields */}
    
  );
}

Loading State

function ContactForm() {
  const { handleSubmit, formState: { isSubmitting } } = useForm();

  return (
    
      {/* fields */}
      
        {isSubmitting ? (
          <>
            
            Sending message...
            Sending...
          
        ) : (
          'Send Message'
        )}
      
    
  );
}

Focus First Error

import { useForm } from 'react-hook-form';
import { useRef, useEffect } from 'react';

function MyForm() {
  const formRef = useRef(null);
  const { handleSubmit, formState: { errors, isSubmitSuccessful } } = useForm();
  
  // Focus first error after failed submit
  useEffect(() => {
    if (Object.keys(errors).length > 0) {
      const firstError = formRef.current?.querySelector('[aria-invalid="true"]');
      (firstError as HTMLElement)?.focus();
    }
  }, [errors]);

  return {/* fields */};
}

File Structure

form-react/
├── SKILL.md
├── references/
│   ├── rhf-patterns.md         # React Hook Form deep-dive
│   ├── tanstack-patterns.md    # TanStack Form deep-dive
│   └── migration-guide.md      # Formik → RHF migration
└── scripts/
    ├── rhf-form-builder.tsx    # RHF form patterns
    ├── tanstack-form-builder.tsx # TanStack patterns
    ├── form-field.tsx          # Reusable field component
    ├── use-form-field.ts       # Custom hook
    └── schemas/                # Shared with form-validation
        ├── auth.ts
        ├── profile.ts
        └── payment.ts

Integration with Other Skills

// Combine: form-react + form-validation + form-accessibility + form-security
import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { loginSchema } from 'form-validation/schemas/auth';
import { FormField } from 'form-accessibility/aria-form-wrapper';
import { AUTOCOMPLETE } from 'form-security/autocomplete-config';

function LoginForm({ onSubmit }) {
  const methods = useForm({
    resolver: zodResolver(loginSchema),
    mode: 'onBlur'
  });

  return (
    
      
        
          
        
        {/* ... */}
      
    
  );
}

Reference

  • references/rhf-patterns.md — Complete React Hook Form patterns
  • references/tanstack-patterns.md — TanStack Form patterns
  • references/migration-guide.md — Migrating from Formik

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.