Khi xây dựng ứng dụng web, một trong những vấn đề thường gặp nhất là xử lý dữ liệu không đúng định dạng từ client gửi lên server, ví dụ như địa chỉ email sai định dạng, mật khẩu quá ngắn hay trường thông tin bỏ trống. Những lỗi tưởng chừng nhỏ nhặt này có thể gây ra nhiều rắc rối, từ thời gian sửa lỗi cho đến các vấn đề về bảo mật. Chính vì vậy, việc sử dụng một công cụ để xác thực dữ liệu trở nên cực kỳ cần thiết. Trong bài viết này, chúng ta sẽ cùng tìm hiểu về Zod, một thư viện tuyệt vời giúp bạn kiểm tra và xác thực kiểu dữ liệu trong các dự án sử dụng TypeScript và Next.js.
1. Zod Là Gì?
Zod là một thư viện JavaScript/TypeScript giúp bạn dễ dàng làm việc với kiểu dữ liệu. Nó cho phép bạn định nghĩa các schema mô tả cách mà dữ liệu bạn mong muốn phải có, từ đó giúp bạn kiểm tra và xác thực dữ liệu thực tế gửi từ client. Nếu dữ liệu không khớp với schema, Zod sẽ thông báo cho bạn biết lỗi cụ thể.
Với Zod, bạn có thể:
- Định nghĩa cấu trúc dữ liệu mong muốn (ví dụ: email phải hợp lệ, mật khẩu phải từ 6 ký tự trở lên).
- Kiểm tra dữ liệu khi nó được gửi lên từ form hoặc API.
- Trả về thông báo lỗi chi tiết nếu dữ liệu không hợp lệ.
- Tích hợp mượt mà với TypeScript, qua đó giúp bạn tránh được nhiều lỗi do dữ liệu bị sai kiểu.
Sơ đồ mô tả cách Zod kiểm tra dữ liệu
2. Tại Sao Nên Dùng Zod Trong Dự Án Next.js?
Next.js là một framework rất phổ biến để xây dựng ứng dụng web, đặc biệt là khi kết hợp với TypeScript. Khi sử dụng Zod trong dự án của bạn, bạn sẽ nhận được nhiều lợi ích sau:
- Xác thực dữ liệu dễ dàng: Zod cho phép bạn xác thực dữ liệu một cách nhanh chóng và hiệu quả trong các API routes.
- Chia sẻ schema: Bạn có thể chia sẻ cùng một schema giữa client và server, giúp giảm thiểu sự lặp lại và giữ cho mã sạch sẽ hơn.
- Giảm lỗi runtime: Khi dữ liệu được kiểm tra chặt chẽ, bạn có thể loại bỏ phần lớn các lỗi xảy ra trong quá trình thực thi.
Thay vì sử dụng các câu lệnh if/else phức tạp để kiểm tra dữ liệu, bạn chỉ cần định nghĩa một schema và để Zod xử lý việc kiểm tra.
3. Những Khái Niệm Cơ Bản Trong Zod
3.1 Schema Là Gì?
Schema trong Zod giống như một bản thiết kế cho dữ liệu. Bạn có thể định nghĩa một schema để chỉ rõ dữ liệu bạn mong muốn, ví dụ như:
import { z } from 'zod';
export const registerSchema = z.object({
email: z.string().email("Email không hợp lệ"),
password: z.string().min(8, "Mật khẩu phải ≥ 8 ký tự"),
name: z.string().nonempty("Họ tên không được trống"),
});
3.2 Một Số Kiểu Dữ Liệu Cơ Bản
Zod hỗ trợ nhiều kiểu dữ liệu khác nhau, bao gồm:
z.string()
cho chuỗiz.number()
cho sốz.boolean()
cho booleanz.object({...})
cho đối tượngz.array(subSchema)
cho mảngz.enum([...])
cho enum
3.3 Các Phương Thức Parse Và SafeParse
schema.parse(data)
: Ném lỗi nếu dữ liệu không hợp lệ.schema.safeParse(data)
: Trả về kết quả mà không ném lỗi.
Khi làm việc ở phía server, thường thì bạn nên sử dụng safeParse
để dễ dàng xử lý lỗi.
3.4 Suy Luận Kiểu (Type Inference)
Zod giúp bạn suy luận kiểu dữ liệu từ schema, qua đó giúp loại bỏ việc viết lại kiểu bằng tay nhiều lần.
type User = z.infer<typeof registerSchema>;
3.5 Refine và Transform
Zod cung cấp cả hai phương thức refine
để thêm logic kiểm tra phức tạp và transform
để thay đổi dữ liệu sau khi xác thực.
4. Tích Hợp Zod Vào API Routes Trong Next.js
Trong thư mục pages/api
, bạn có thể tạo các route API và tích hợp Zod như sau:
import { NextApiRequest, NextApiResponse } from 'next';
import { registerSchema } from '../../lib/schemas/register-schema';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const parsed = registerSchema.safeParse(req.body);
if (!parsed.success) {
return res.status(400).json({
error: "Dữ liệu không hợp lệ",
details: parsed.error.format()
});
}
// Tiến hành xử lý dữ liệu khi được xác thực
return res.status(200).json({ message: "Đăng ký thành công!" });
}
5. Xác Thực Dữ Liệu Trên Frontend
Khi làm việc với frontend, bạn có thể kết hợp Zod với React Hook Form để xác thực ngay lập tức dữ liệu người dùng nhập vào:
import React from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { registerSchema } from '../lib/schemas/register-schema';
const RegisterPage = () => {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(registerSchema)
});
const onSubmit = async data => {
const res = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!res.ok) {
const errorData = await res.json();
console.error("Lỗi từ server:", errorData);
return;
}
alert("Đăng ký thành công!");
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Email: </label>
<input type="text" {...register('email')} />
{errors.email && <p style={{ color: 'red' }}>{errors.email.message}</p>}
</div>
<div>
<label>Mật khẩu: </label>
<input type="password" {...register('password')} />
{errors.password && <p style={{ color: 'red' }}>{errors.password.message}</p>}
</div>
<div>
<label>Họ tên: </label>
<input type="text" {...register('name')} />
{errors.name && <p style={{ color: 'red' }}>{errors.name.message}</p>}
</div>
<button type="submit">Đăng ký</button>
</form>
);
};
6. Một Vài Lời Khuyên Khi Sử Dụng Zod
- Tách riêng schemas: Đặt schemas vào thư mục riêng để quản lý dễ hơn.
- Tái sử dụng schema: Chỉ định nghĩa một lần và sử dụng chung cho cả frontend và backend.
- Sử dụng inference: Luôn dùng
type MyType = z.infer<typeof mySchema>
để tránh nhầm lẫn. - Xử lý lỗi rõ ràng: Đảm bảo gửi thông báo lỗi chi tiết về cho client để người dùng sửa lỗi dễ dàng hơn.
7. Kết Luận
Zod là một công cụ mạnh mẽ không chỉ trong Next.js mà còn trong nhiều dự án JavaScript/TypeScript khác. Hy vọng rằng bài viết này đã giúp bạn hiểu rõ hơn về cách sử dụng Zod để xác thực dữ liệu và cải thiện chất lượng mã nguồn trong dự án của bạn. Hãy thử áp dụng Zod và bạn sẽ thấy nhiều lợi ích mà nó mang lại cho quy trình phát triển của bạn. Đừng quên ghé thăm comdy.vn để cập nhật thêm nhiều kiến thức marketing thú vị!