表單是每個開發人員都會遇到的東西,無論是作為使用者還是開發人員。它們對於大多數網站來說都是必不可少的,但它們的複雜性可能差異很大——從簡單的3 欄位聯絡表單到giga-monster-t-rex、具有150 個欄位、動態驗證和非同步檢查的多頁表單。
在這篇文章中,我們將探討如何使用 React Hook Form、Zod 和 Shadcn 建立一個適應性強、開發人員友善的解決方案,輕鬆處理各種表單需求。
這是我們將在這篇文章中開發的表單。我計劃寫另一篇關於表單高級使用的文章,後續將更加複雜,敬請期待 😃
讓我們看一下將用於建置和管理表單的堆疊。
框架: Wasp (React、Node.js 和 Prisma 的全端框架)。
使用 React 實現快速、高效的全端 Web 開發和部署。
用於在 React 中製作表單的輕量級程式庫,主要透過其useForm
鉤子。
處理表單驗證、錯誤管理,並提供靈活的驗證方法以及與各種 UI 元件庫的整合。
TypeScript-first 驗證函式庫,用於建立詳細的、可重複使用的驗證模式。
與 TypeScript 類型整合以保持驗證統一並避免重複。
直接嵌入專案中的可重複使用 UI 元件的集合,允許開發人員僅採用他們需要的內容並自訂這些元件。
提供對 React Hook Form 和 Zod 的內建支援。
下面是一個範例片段,展示了 Shadcn 庫中的表單欄位:
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
即使您喜歡使用不同風格的堆疊,只要您堅持使用 React 和 RHF,這仍然是一個可以幫助您繼續前進的有效範例。
我們將用來示範基本表單的應用程式是一個具有基本 CRUD 操作的管理面板。它將包括電子郵件和密碼身份驗證,並由兩個頁面組成:一個顯示所有用戶表的主螢幕,以及一個用戶建立頁面,這將是本文的重點。
我們的表單將包括驗證,以確保使用者在不符合指定要求的情況下無法提交表單(即建立新使用者)。 User 物件是驗證範例的絕佳候選者,因為它包含適合不同驗證的各種資料類型:字串、日期(例如出生日期)、電子郵件字串和布林值(例如高級使用者狀態)。完整的 Prisma 架構文件如下所示。
model Customer {
id Int @id @default(autoincrement())
name String
surname String
email String
dateOfBirth DateTime
premiumUser Boolean
}
為了快速啟動我們的專案,我們將使用具有 TypeScript 的預定義Wasp 模板,稱為todo-ts 。此範本附帶了現成的元件和驗證路由,包括登入和註冊畫面。它還提供了有關 Wasp 中 CRUD 操作如何運作的可靠範例,如果您是該框架的新手,它是理想的選擇。此外,我們將利用新的 Wasp TypeScript SDK 來管理我們的配置,因為它提供了擴充的客製化靈活性。
Wasp團隊正在努力建立這樣的內容,更不用說建立一個現代的開源 React/NodeJS 框架了。
表達您支援的最簡單方法就是為 Wasp 儲存庫加註星標! 🐝 但如果您可以查看儲存庫(用於貢獻,或只是測試產品),我們將不勝感激。點擊下面的按鈕給黃蜂星一顆星並表示您的支持!
{% cta https://github.com/wasp-lang/wasp %} ⭐️ 感謝您的支持 💪 {% endcta %}
為了使用表單,我們先定義 Zod 驗證模式。我們的表單有三種資料類型:字串、日期和布林值。我們將對大多數欄位surname
驗證: name
是必需的,而email
則使用內建的電子郵件驗證。 Zod 透過針對不同類型(例如電子郵件、URL 和 UUID)的內建驗證簡化了常見字串類型的驗證,這對我們的電子郵件領域很有幫助。
對於其他驗證,日期不能設定為未來日期,且premiumUser
欄位只需為布林值即可。 Zod 也提供預設的驗證錯誤訊息,但這些訊息可以自訂。例如,我們可以指定名稱: z.string().min name: z.string().min(1, 'Name is required')
name: z.string().min(1)
。
const formSchema = z.object({
name: z.string().min(1, { message: 'Name is required' }),
surname: z.string().min(1, { message: 'Surname is required' }),
email: z.string().email({ message: 'Invalid email address' }),
dateOfBirth: z
.date()
.max(new Date(), { message: 'Date cannot be in the future' }),
premiumUser: z.boolean(),
});
我們的表單由React Hook Form中的useForm
鉤子管理,它提供了廣泛的選項來處理和驗證表單值、檢查錯誤和管理表單狀態。為了整合我們的 Zod 驗證模式,我們將使用 Zod 解析器,讓 React Hook Form 應用我們先前定義的驗證。
表單的defaultValues
派生自客戶物件。由於該元件用於新增客戶和編輯現有客戶,因此我們將傳遞必要的資料作為輸入。對於新客戶,使用一些合理的預設值;對於現有客戶,從資料庫中檢索資料。除了設定預設值和決定是否呼叫createCustomer
還是updateCustomer
之外,表單處理的所有其他方面都保持不變。
type FormData = z.infer<typeof formSchema>
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: customer,
});
最後一步是建立表單本身並將其組裝到 TSX 檔案中。如前所述,這個過程很簡單。無論我們使用文字輸入、日期選擇器還是帶有 Shadcn 控制項的複選框,我們都遵循類似的結構:
首先建立FormField
元素並設定其control
、 name
和render
屬性。
render
屬性是關鍵,因為它包含表單元素本身。
通常,我們將所有內容包裝在FormItem
中,為標籤新增FormLabel
,並使用適當的值和 setter 方法將受控表單元素放入FormControl
中。
最後,我們在下面新增FormMessage
,如果驗證失敗,它會顯示 Zod 驗證訊息。
// Defining form schema
const formSchema = z.object({
dateOfBirth: z.date().max(new Date(), {
message: 'Date of birth cannot be today, or in the future',
}),
});
// Defining form
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: defaultValues,
});
// Creating form control
<FormField
control={form.control}
name="dateOfBirth"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Date of birth</FormLabel>
<FormControl>
<DatePicker date={field.value} setDate={field.onChange} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
如果您想查看完整的應用程式,請查看此處的 GitHub 儲存庫: GitHub Repo 。我希望本文能使表單的使用變得更加容易,如果您對更多與表單相關的內容感興趣,請繼續關注第二部分!在下一部分中,我們將深入研究高級模式和驗證技術來增強您的應用程式。
如果您喜歡這篇文章,請考慮在 GitHub 上為Wasp加註星標!您的支持幫助我們繼續為每個人提供更輕鬆、更順暢的 Web 開發。 🐝
原文出處:https://dev.to/wasp/building-react-forms-with-ease-using-react-hook-form-zod-and-shadcn-4f4i