Tài liệu đọc thêm cho Lab 4.2 (form tạo và sửa công việc). Code mẫu viết cho react-hook-form 7, zod 4 và @hookform/resolvers 5. Nếu dự án của bạn dùng phiên bản khác, hãy đối chiếu tại react-hook-form.com và zod.dev.

Vì sao cần React Hook Form?

Form tạo công việc có 4 trường. Nếu tự quản lý bằng useState, bạn phải viết state cho từng trường, state cho lỗi, cờ “đang lưu”, rồi tự kiểm tra từng điều kiện. Form càng nhiều trường, code càng rối. React Hook Form gom toàn bộ việc đó vào một hook useForm. Kết hợp với Zod, bạn khai báo quy tắc hợp lệ ở một chỗ duy nhất:

Cài đặt

Form mẫu bên dưới dùng thêm date picker để chọn hạn hoàn thành:

Bước 1 — Viết schema cho công việc

Schema là “luật” của form. Đặt nó trong file riêng để dùng lại cho cả form tạo lẫn form sửa.
src/features/tasks/taskSchema.ts
  • .trim() cắt khoảng trắng, nên tiêu đề chỉ gồm dấu cách vẫn bị báo lỗi.
  • .refine() dùng cho quy tắc tự đặt, ở đây là “hạn không ở quá khứ”.
  • z.infer sinh kiểu TypeScript từ schema, bạn không cần khai báo kiểu TaskFormValues bằng tay.

Bước 2 — Dựng form với Controller

Trên web, React Hook Form thường dùng register. Trong React Native, TextInput không phải thẻ input HTML nên phải dùng Controller. Nếu AI sinh code {...register('title')} cho React Native, đó là code sai.
src/features/tasks/TaskForm.tsx

Đọc hiểu nhanh

Trường ưu tiên và hạn hoàn thành không phải TextInput, nhưng vẫn dùng Controller theo cùng một cách: lấy value để hiển thị, gọi onChange khi người dùng chọn. Đây là mẫu bạn sẽ dùng cho mọi component nhập liệu tự dựng.

Bước 3 — Dùng form cho cả tạo và sửa

createTask và updateTask là hàm lưu dữ liệu của bạn. Ở buổi 4 chúng cập nhật dữ liệu mẫu, sang buổi 5 sẽ ghi lên Firebase. Form không cần thay đổi.

Prompt mẫu cho AI

Lỗi AI hay mắc — cần kiểm tra

register là cách viết cho web. Trong React Native, giá trị gõ vào sẽ không được form ghi nhận. Yêu cầu AI chuyển sang Controller.
TextInput có cả onChange (trả về event) và onChangeText (trả về chuỗi). Phải gắn field.onChange vào onChangeText, nếu không form sẽ không nhận đúng chữ người dùng gõ.
Thiếu defaultValues thì value ban đầu của các trường là undefined. Ví dụ ở trên sẽ lỗi ngay khi gọi value.toLocaleDateString(...) cho trường hạn. Luôn khai báo đủ giá trị ban đầu cho mọi trường.
Nếu AI viết if (!values.title) Alert.alert(...) trong onSubmit, quy tắc đang bị viết hai nơi. Mọi quy tắc nên nằm trong schema Zod.

Tự kiểm tra

  • Bấm Lưu khi tiêu đề trống hoặc chỉ có dấu cách → hiện lỗi dưới ô tiêu đề, không lưu
  • Chọn hạn là ngày hôm qua → hiện lỗi dưới trường hạn
  • Mở form sửa → các trường điền sẵn đúng dữ liệu của công việc
  • Bấm Lưu liên tục nhiều lần → chỉ lưu một lần