Zod in React API Validation
1 min read
文章概述
本文主要介绍了如何在 React 应用中使用 Zod 进行 API 响应数据的验证。Zod 是一个 TypeScript 优先的数据验证库,可以通过定义明确的数据格式(schema)来确保 API 返回的数据符合预期,从而避免因数据不一致导致的错误。
核心内容
-
为什么选择 Zod?
- 清晰的 Schema 定义:用简洁的规则描述 API 响应数据的结构,增强代码可读性和维护性。
- 数据验证:支持对各种数据类型的严格验证(如必填字段、格式检查等)。
- 早期错误检测:在 API 调用时就能发现数据不一致,防止后续的应用错误。
- 提高开发体验:通过类型安全的编码方式减少手动类型检查,提高开发效率。
- 单一数据定义源:集中管理数据模型,确保整个应用的数据一致性。
-
新建 TypeScript React 项目
- 使用 Vite 快速生成 React 项目:
1 2 3 4
npm create vite@latest my-react-app -- --template react-ts cd my-react-app npm install npm run dev
- 安装 Zod:
1
npm install zod
- 使用 Vite 快速生成 React 项目:
-
Zod 的基本用法和验证
- 定义数据类型:使用
z.string()
、z.number()
、z.object()
等方法定义预期的数据格式。例如:1 2 3 4 5 6 7 8 9
import { z } from 'zod'; const userName = z.string().min(5).max(10); // 字符串,长度在 5 到 10 之间 const userAge = z.number().positive().int(); // 正整数 const userEmail = z.string().email(); // 合法的邮箱格式 console.log(userName.parse('John Doe')); // 有效输出: John Doe console.log(userAge.parse(30)); // 有效输出: 30 console.log(userEmail.parse("[email protected]")); // 有效输出: [email protected]
- 添加验证规则:通过链式调用(如
min
、max
、positive
、int
、email
)可以进一步约束数据格式。若数据不满足规则(如字符串超过最大长度),则会抛出ZodError
。
- 定义数据类型:使用
-
解析数据:parse 与 safeParse
- parse 方法:直接解析数据,不符合规则时会抛出错误,可能会中断应用流程。
- safeParse 方法:返回一个对象,其中包含
success
(布尔值)以及data
或error
字段,推荐用于生产环境,以便优雅处理错误。
例如,使用 safeParse 处理用户数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
const userSchema = z.object({ name: userName, age: userAge, email: userEmail, }); const userData = { name: "John Doe", age: 24, email: "[email protected]" }; const result = userSchema.safeParse(userData); console.log(result); // 包含数据和成功状态的对象
-
为 API 响应构建 Zod Schema
- 以 JSONPlaceholder 的帖子数据为例:
1 2 3 4 5 6
{ "userId": 1, "id": 3, "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut", "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut" }
- 定义帖子数据的 schema:
1 2 3 4 5 6 7 8 9 10
import { z } from 'zod'; const postSchema = z.object({ userId: z.number().positive().int(), id: z.number().positive().int(), title: z.string(), body: z.string() }); const postSchemaArray = z.array(postSchema); // 数组的 schema
- 以 JSONPlaceholder 的帖子数据为例:
-
在 React 中集成 Zod 与 API 调用
- 结合
useEffect
和fetch
从 API 获取数据,并使用 Zod 验证数据:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
import { z } from 'zod'; import { useEffect } from 'react'; const postSchema = z.object({ userId: z.number().positive().int(), id: z.number().positive().int(), title: z.string(), body: z.string() }); const postSchemaArray = z.array(postSchema); // 数组的 schema type Posts = z.infer<typeof postSchemaArray>; // 推断出 posts 的类型 const ZodApi = () => { useEffect(() => { fetch("https://jsonplaceholder.typicode.com/posts") .then((response) => response.json()) .then((posts: Posts) => { const validatedPosts = postSchemaArray.safeParse(posts); if (validatedPosts.success === false) { console.log("Validation Error:", validatedPosts.error); return; } console.log(validatedPosts.data); }); }, []); return <div>ZodApi</div>; }; export default ZodApi;
- 该组件展示了如何通过验证后再使用 API 数据,同时如何处理验证错误,保证 UI 不会因数据异常而崩溃。
- 结合
-
UI 渲染与错误处理
- 利用 React 的状态管理(useState)来存储和展示验证后的数据,以及处理加载和错误状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
import { z } from "zod"; import { useEffect, useState } from "react"; const postSchema = z.object({ userId: z.number().positive().int(), id: z.number().positive().int(), title: z.string(), body: z.string(), }); const postSchemaArray = z.array(postSchema); type Posts = z.infer<typeof postSchemaArray>; const ZodApi = () => { const [posts, setPosts] = useState<Posts>([]); const [error, setError] = useState(""); useEffect(() => { fetch("https://jsonplaceholder.typicode.com/posts") .then((response) => response.json()) .then((posts: Posts) => { const validatedPosts = postSchemaArray.safeParse(posts); if (validatedPosts.success === false) { console.log(validatedPosts.error.name); setError(validatedPosts.error.message); return; } console.log(validatedPosts.data); setPosts(validatedPosts.data) }); }, []); if (!posts.length && !error) { return <div>Loading posts...</div>; } if (error) { return <div>Error fetching Data</div>; } return ( <div> <h1>Posts</h1> <ol> {posts.map((post) => ( <li key={post.id}> {post.title} </li> ))} </ol> </div> ); }; export default ZodApi;
- 此示例展示了如何根据状态显示加载提示、错误信息以及最终渲染出 100 个帖子的列表。
- 利用 React 的状态管理(useState)来存储和展示验证后的数据,以及处理加载和错误状态:
总结
通过在 React 项目中引入 Zod,开发者可以:
- 预先定义好 API 数据格式,提高数据的可靠性和一致性;
- 通过
safeParse
优雅地捕获数据验证错误,防止因异常数据导致应用崩溃; - 更加便捷地维护和管理数据类型,提升开发体验和效率。
整体来看,Zod 不仅提升了代码的健壮性,还能让调试和维护过程变得更加直观和简单,对于构建大型 React 应用尤为重要。