원클릭으로
form-validation
Guide for implementing form handling with React Hook Form and Zod validation. Use when creating forms with validation.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Guide for implementing form handling with React Hook Form and Zod validation. Use when creating forms with validation.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Checklist for auditing and fixing accessibility issues (WCAG 2.1 AA compliance). Use when reviewing components or pages for accessibility.
Guide for creating RESTful API endpoints with validation and error handling. Use when implementing backend API routes.
Guide for implementing secure authentication with JWT and session management. Use when adding authentication to an application.
Guide for creating responsive layouts with CSS. Use when implementing responsive design or fixing layout issues.
Guide for designing database schemas with Prisma ORM. Use when creating or modifying database models.
Guide for consistent error handling across frontend and backend. Use when implementing error handling logic.
| name | form-validation |
| description | Guide for implementing form handling with React Hook Form and Zod validation. Use when creating forms with validation. |
Follow this process to implement robust form validation:
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const formSchema = z.object({
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
age: z.number().int().positive().optional(),
});
type FormData = z.infer<typeof formSchema>;
export function LoginForm() {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm<FormData>({
resolver: zodResolver(formSchema),
});
const onSubmit = async (data: FormData) => {
try {
await loginUser(data);
} catch (error) {
console.error(error);
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Form fields */}
</form>
);
}
<div>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
{...register('email')}
aria-invalid={errors.email ? 'true' : 'false'}
/>
{errors.email && (
<span role="alert" className="error">
{errors.email.message}
</span>
)}
</div>
const schema = z.object({
password: z.string().min(8),
confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
message: "Passwords don't match",
path: ['confirmPassword'],
});
const schema = z.object({
username: z.string().refine(
async (username) => {
const exists = await checkUsernameAvailability(username);
return !exists;
},
{ message: 'Username already taken' }
),
});
// Email
email: z.string().email()
// Password (strong)
password: z.string()
.min(8)
.regex(/[A-Z]/, 'Must contain uppercase')
.regex(/[a-z]/, 'Must contain lowercase')
.regex(/[0-9]/, 'Must contain number')
// URL
url: z.string().url()
// Phone
phone: z.string().regex(/^\+?[1-9]\d{1,14}$/)
// Date
birthdate: z.string().refine((val) => !isNaN(Date.parse(val)))
// File upload
file: z.instanceof(File)
.refine((file) => file.size <= 5000000, 'Max 5MB')
.refine(
(file) => ['image/jpeg', 'image/png'].includes(file.type),
'Only .jpg and .png files'
)
// Select
<select {...register('country')}>
<option value="">Select country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
</select>
// Checkbox
<input
type="checkbox"
{...register('terms')}
/>
// Schema
const schema = z.object({
country: z.string().min(1, 'Please select a country'),
terms: z.boolean().refine((val) => val === true, {
message: 'You must accept the terms',
}),
});
<button
type="submit"
disabled={isSubmitting}
>
{isSubmitting ? 'Submitting...' : 'Submit'}
</button>
const onSubmit = async (data: FormData) => {
try {
await submitForm(data);
toast.success('Form submitted successfully');
} catch (error) {
if (error instanceof ApiError) {
toast.error(error.message);
} else {
toast.error('An unexpected error occurred');
}
}
};