next中shadcn、React Hook Form、zod 使用教程

要在 Next 项目中结合 shadcn、React Hook Form 和 zod 使用表单验证,可以按照以下步骤来设置和使用这些工具。我们将搭建一个简单的表单,包含姓名和邮箱字段,并使用 zod 进行表单验证, React Hook Form 管理表单状态

1. 安装依赖

首先,确保安装所需的库。

npm install @hookform/resolvers react-hook-form zod

2. 定义表单验证 Schema

使用 zod 定义表单字段的验证规则。zod 的 Schema 将帮助我们在表单中验证输入数据。

// src/schemas/userFormSchema.js

import { z } from 'zod';

export const userFormSchema = z.object({
  name: z.string().min(1, { message: '姓名不能为空' }),
  email: z.string().email({ message: '无效的邮箱格式' }),
});

3. 创建表单组件

在表单组件中使用 React Hook FormzodResolver

zodResolver 是一个适配器,它将 Zod 的 schema 用于 React Hook Form 的验证。在提交表单时,它会自动验证输入数据是否符合 Zod 定义的规则。

// src/components/UserForm.js

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { userFormSchema } from '@/schemas/userFormSchema';
import { useState } from 'react';

export default function UserForm() {
  const [submitMessage, setSubmitMessage] = useState('');
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(userFormSchema),
  });

  const onSubmit = (data) => {
    console.log('Form Data:', data);
    setSubmitMessage('表单提交成功');
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      {/* 姓名字段 */}
      <div>
        <label className="block text-sm font-medium text-gray-700">姓名</label>
        <input
          type="text"
          {...register('name')}
          className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
        />
        {errors.name && <p className="text-sm text-red-500">{errors.name.message}</p>}
      </div>

      {/* 邮箱字段 */}
      <div>
        <label className="block text-sm font-medium text-gray-700">邮箱</label>
        <input
          type="email"
          {...register('email')}
          className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
        />
        {errors.email && <p className="text-sm text-red-500">{errors.email.message}</p>}
      </div>

      {/* 提交按钮 */}
      <button
        type="submit"
        className="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
      >
        提交
      </button>

      {/* 提交状态信息 */}
      {submitMessage && <p className="text-sm text-green-500">{submitMessage}</p>}
    </form>
  );
}

4. 使用 shadcn UI 组件样式

通过 shadcn 的样式,可以自定义表单的外观。例如,可以将输入框样式更改为 @/components/ui/input 或按钮样式为 @/components/ui/button

import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

export default function UserForm() {
  // 代码同上
  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <label className="block text-sm font-medium text-gray-700">姓名</label>
        <Input type="text" {...register('name')} />
        {errors.name && <p className="text-sm text-red-500">{errors.name.message}</p>}
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700">邮箱</label>
        <Input type="email" {...register('email')} />
        {errors.email && <p className="text-sm text-red-500">{errors.email.message}</p>}
      </div>
      <Button type="submit">提交</Button>
      {submitMessage && <p className="text-sm text-green-500">{submitMessage}</p>}
    </form>
  );
}

5. 将组件添加到页面

在页面文件中导入并使用 UserForm 组件:

import UserForm from '@/components/UserForm';

export default function HomePage() {
  return (
    <div className="p-4">
      <h1 className="text-xl font-semibold">用户注册</h1>
      <UserForm />
    </div>
  );
}

### 如何在 Router App 中使用 Shadcn/UI 或 Shadcn/UI 与 Router App 的集成 Shadcn/UI 是一个基于 Tailwind CSS 构建的高质量 UI 组件库,适用于现代前端框架如 ReactNext.js。以下是关于如何在 Router App(例如 Next.js 应用程序中的 `app` 路由器模式)中集成和使用 Shadcn/UI 的详细说明。 #### 集成步骤 1. **初始化项目** 如果尚未创建 Next.js 项目,则可以通过以下命令快速启动一个新的 Next.js 13+ 项目[^4]: ```bash npx create-next-app@latest my-app --typescript --eslint --tailwind --src-dir cd my-app ``` 2. **安装 Shadcn/UI** 安装所需的依赖项以启用 Shadcn/UI 功能。运行以下命令来安装必要的包: ```bash npm install @shadcn/ui react-dom ``` 3. **配置 Tailwind CSS** 确保项目的 Tailwind CSS 已正确定义并加载了 Shadcn/UI 所需的扩展样式。如果需要自定义或移除某些部分,请参考文档调整 `tailwind.config.js` 文件的内容。 4. **引入组件** 将 Shadcn/UI 提供的基础组件导入到您的应用程序中。例如,在布局文件 (`app/layout.tsx`) 中可以这样写入基础结构代码: ```tsx import "./globals.css"; import { Button } from "@/components/ui/button"; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body> {/* Example of using a button component */} <Button variant="default">Click Me</Button> {children} </body> </html> ); } ``` 5. **设置路由保护机制** 对于涉及用户身份验证的应用场景,可借鉴 React 基于 shadcn/ui 实现登录/注销功能的经验[^2]。具体来说,利用 Next.js 的中间件或者客户端逻辑完成对未授权用户的重定向处理。下面是一个简单的例子展示如何结合 Shadcn/UI 表单组件实现登录界面: ```tsx "use client"; import { useState, useEffect } from "react"; import { useForm } from "react-hook-form"; import * as z from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; const loginSchema = z.object({ email: z.string().email(), password: z.string().min(6), }); type LoginInputs = z.infer<typeof loginSchema>; export default function LoginPage() { const [loading, setLoading] = useState(false); const { register, handleSubmit, formState: { errors }, } = useForm<LoginInputs>({ resolver: zodResolver(loginSchema), }); async function onSubmit(data: LoginInputs) { try { setLoading(true); // Simulate API call here... console.log({ data }); } catch (error) { alert(error.message || "An error occurred."); } finally { setLoading(false); } } return ( <div className="flex flex-col items-center justify-center h-screen gap-8"> <h1 className="text-2xl font-bold text-gray-900">Sign In</h1> <form onSubmit={handleSubmit(onSubmit)} className="space-y-4 w-full max-w-md" > <div> <Label htmlFor="email">Email Address</Label> <Input id="email" placeholder="example@example.com" {...register("email")} /> {errors.email && ( <p className="mt-1 text-sm text-red-700">{errors.email?.message}</p> )} </div> <div> <Label htmlFor="password">Password</Label> <Input id="password" type="password" autoComplete="current-password" {...register("password")} /> {errors.password && ( <p className="mt-1 text-sm text-red-700"> {errors.password?.message} </p> )} </div> <Button disabled={loading} type="submit"> Sign In </Button> </form> </div> ); } ``` 6. **优化用户体验** 参考已有的最佳实践案例,比如官方提供的 dashboard starter kit[^3],从中学习更多高级技巧用于增强实际开发过程中的效率与质量。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值