Skip to main content

# Xử lý form với Ant Design (Phần 1)

March 19, 2023 · 7 min read
Gia Hung
Creator of Web totals

Cách xử lý form trong Ant Design sao cho đúng.

## 1. Cơ chế hoạt động​

Ta xét một ví dụ đơn giản như sau:

Như ta thấy khi đặt component `Input` trong `Form.Item` với `name` là `username` thì khi submit sẽ nhận được một object với key là `username` và value là giá trị của input.

Vậy có phải cứ đặt `Input` bên trong `Form.Item` là ta sẽ lấy được value của Input khi submit không? Mình sẽ custom xíu là thêm cái label hoặc cần tuỳ biến input thêm prefix hoặc suffix icon,...

Vẫn cho mình cùng kết quả. nếu ta muốn dùng nhiều nơi thì phải copy sang nhiều chỗ khác nhau. vậy mình sẽ tách thành một component để sau có thể tái sử dụng

Mình kiểm tra lại kết quả xem sao. Ops kết quả không như ta mong đợi. Khi tách thành component để có thể tái sử dụng thì không còn lấy được value của `input` nữa. Vậy chuyện gì đã xảy ra mà khi đặt trong `Form.Item` thì có kết quả và mình muốn tách ra có thể tái sử dụng lại không hoạt động.

Mình sẽ kiểm tra `props` của `CustomInput` xem có gì bất thường không nhé =)))

note

Như ta thấy `props` của `CustomInput` là một object chứa `id`, `value`, `onChange`. Tức là khi ta đặt Input ngay bên trong `Form.Item` thì nó tự động pass props đó vào cho `Input` vì vậy ta sẽ lấy được value của Input.

Khi mình tách ra thành một component để tái sử dụng thì `value` và `onChange` sẽ không được pass vào Input nữa nên ta sẽ không lấy được value của Input

Ok. vậy mình sẽ thử fix bằng cách pass `value` và `onChange` vào Input xem sao.

Oh. Hihi kết quả như mong đợi

note

Kết luận: Khi ta muốn truyền value từ component bất kì lên `Form.Item` ta chỉ cần dùng hàm `onChange` từ `Form.Item` cái mà được truyền xuống props khi đặt component trong `Form.Item`

## 2. Cơ chế hoạt động `dependencies`, `shouldUpdate` và `useWatch`​

### a. Dependencies​

Mình có một ví dụ đơn giản như sau: có 3 select gồm tỉnh, huyện, xã. Yêu cầu: Khi chọn tỉnh thì sẽ tải danh sách huyện, khi chọn huyện thì sẽ tải danh sách xã.

Sẽ có nhiều cách xử lý bài toán này. như một số anh em sẽ xử lý bằng cách dùng state lưu lại giá trị tỉnh, huyện, xã. có thay đổi về state thì lắng nghe trong `useEffect` để tải list huyện, xã. Cách này sẽ ảnh hưởng đến performance nếu mà form có nhiều field.

Ở đây mình sẽ chọn cách giải quyết băng cách dùng `dependencies`

Đầu tiên mình sẽ tạo custom select tỉnh, huyện, xã:

Bình thường data sẽ được lấy từ API nhưng trong ví dụ này mình sẽ tải về sẵn luôn.

File App của mình

Kết quả:

Hiện tại thì bạn đã thấy là chưa thể chọn được huyện và xã. giờ mình sẽ thêm `dependencies` để mỗi khi chọn xong tỉnh thì huyện sẽ update lại

Mình sẽ wrap bằng 1 `Form.Item` nữa và thêm `dependencies` là mảng name của item mà mình sẽ muốn xem sự thay đổi. Log props ở trên ra thì mình sẽ thấy được các method của form instance

Với `SelectDistrict` mình cần truyền thêm prop `province`

Với `SelectWard` mình cần truyền thêm prop `district`

Đây là kết quả đạt được:

danger

Một điều nữa là mình cần làm là reset field đã chọn khi mình thay đổi tỉnh hoặc huyện khác =)))) Bạn có thể giúp mình làm cái này đúng không xD

### b. shouldUpdate​

tip

Với `shouldUpdate` thì cũng sẽ tương tự như `dependencies` nhưng nếu để `shouldUpdate` là true thì mỗi khi field nào trong form thay đổi thì component của mình sẽ re-render lại, để tránh re-render thì mình sẽ truyền vào 1 callback function để kiểm tra field nào mình muốn kiểm tra sự thay đổi

Kết quả cũng tương tự như dùng `dependencies`

### c. useWatch​

`useWatch` là một hook được cung cấp bới form antd, dùng để lắng nghe những field mà có thay đổi

Mình sẽ update lại 2 component select của mình như sau: Thay vì truyền từ props xuống thì mình dùng `useWatch` để lấy data mới nhất khi có thay đổi

Kết quả vẫn như mình mong đợi:

- 1. Cơ chế hoạt động
- 2. Cơ chế hoạt động `dependencies`, `shouldUpdate` và `useWatch`
  - a. Dependencies
  - b. shouldUpdate
  - c. useWatch