Communitygithub.com

sakilanwar12/nextjs-typescript-skills

用于使用 react-hook-form 和 zod 构建表单——基于模式校验、类型化字段、服务端操作提交、无障碍错误提示和文件输入。

nextjs-typescript-skills 是什么?

这是一个专注于在 Next.js TypeScript 项目中使用 react-hook-form 和 zod 构建表单的 AI 技能。它遵循“模式优先”的原则,要求开发者首先定义 zod 校验模式,并通过 `z.infer` 自动推导 TypeScript 类型,确保客户端和服务端共享唯一的真实数据源。该技能强制使用 `@hookform/resolvers/zod` 的 `zodResolver`,并建议将表单模式设置为 `onTouched` 以优化用户体验。此外,它强调无障碍性,要求为每个字段添加 `aria-invalid`、`aria-describedby` 等属性,并使用 `role="alert"` 显示错误信息。表单提交通常通过 Server Action 实现,需要处理待提交状态和服务器错误。技能提供了一个完整的 `LoginForm` 组件示例,并附带一个检查清单,帮助开发者确保所有关键步骤都已正确实现。该技能适用于 Cursor、Codex、Windsurf 等支持技能规范的 AI 代理平台。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sakilanwar12/nextjs-typescript-skills/tree/HEAD/skills/nextjs-forms

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

表单 (react-hook-form + zod)

规则

  1. 模式优先:定义 zod 模式,通过 z.infer 派生类型。客户端和服务端共享唯一的真实数据源。
  2. 使用 @hookform/resolvers/zod(zodResolver)。模式设置为 onTouched 以优化用户体验;在服务端操作中再次使用相同模式进行校验。
  3. 为表单指定类型:useForm<FormValues>。不允许出现 any 类型的字段值。
  4. 无障碍错误提示:为错误消息添加 aria-invalid、aria-describedby、role="alert" 属性。使用 <label htmlFor> 关联标签。
  5. 通过 Server Action(formAction 或调用服务端函数的 action)提交。显示待提交状态和服务器错误状态。

模式

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

const Schema = z.object({
  email: z.string().email('请输入有效的邮箱地址'),
  password: z.string().min(8, '至少 8 个字符'),
});
type Values = z.infer<typeof Schema>;

export function LoginForm({ onSubmit }: { onSubmit: (v: Values) => Promise<{ ok: boolean; error?: string }> }) {
  const { register, handleSubmit, formState: { errors, isSubmitting }, setError } = useForm<Values>({
    resolver: zodResolver(Schema),
    mode: 'onTouched',
  });

  return (
    <form onSubmit={handleSubmit(async (v) => {
      const r = await onSubmit(v);
      if (!r.ok) setError('root', { message: r.error ?? '操作失败' });
    })}>
      <label htmlFor="email">邮箱</label>
      <input id="email" type="email" autoComplete="email"
        aria-invalid={!!errors.email} aria-describedby={errors.email ? 'email-err' : undefined}
        {...register('email')} />
      {errors.email && <p id="email-err" role="alert">{errors.email.message}</p>}

      <label htmlFor="password">密码</label>
      <input id="password" type="password" autoComplete="current-password" {...register('password')} />
      {errors.password && <p role="alert">{errors.password.message}</p>}

      {errors.root && <p role="alert">{errors.root.message}</p>}
      <button disabled={isSubmitting}>{isSubmitting ? '正在登录…' : '登录'}</button>
    </form>
  );
}

检查清单

  • 是否已定义 zod 模式并导出 z.infer 类型?
  • 是否已接入 zodResolver?
  • 是否每个字段都有 label 和 aria 属性?
  • 服务端是否使用相同的模式重新校验?
  • 是否已显示待提交禁用状态和根/服务端错误?

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

相关技能