- vị trí đặt
modalIsVisiblevà state lifting - sử dụng childern để chèn nội component khác vào modal
- condition rendering để mở và đóng modal
- conditional rendering để thay đổi trạng thái nút
useState bằng một ví dụ thực tế: Modal — component xuất hiện ở khắp mọi nơi trong production, và là bài tập tổng hợp hoàn hảo cho state lifting, conditional rendering, và children props.
Mục tiêu cuối bài: click “New Post” → modal mở ra chứa form → submit hoặc click backdrop/nút X → modal đóng lại.
State đặt ở đâu?
Câu hỏi đầu tiên cần trả lời trước khi viết code:isModalOpen đặt trong component nào?
Muốn biết, phải hiểu rõ cấu trúc của các component.
Cấu trúc component
- Nút “New Post” nằm trong
PostList. - Nút X và backdrop nằm trong
Modal. NewPostchỉ là form thuần — không biết gì về modal.
PostList— cần biết để render nút “New Post” hay “Đang mở…”Modal— cần biết để render hay không renderNewPost— không cần biết, chỉ lo render form
PostList là cha chung của cả Modal lẫn nút “New Post” — nên isModalOpen đặt ở đây.
Children Props và render cái gì bên trong Modal
Trước khi viếtModal, cần hiểu children props — một loại props đặc biệt trong React.
Thông thường bạn truyền data qua props có tên cụ thể: title, author, onSubmit… Nhưng Modal không biết trước bên trong nó sẽ chứa gì — lúc thì NewPost, lúc thì form đăng nhập, lúc thì hộp thoại xác nhận xóa.
children giải quyết điều đó: bất cứ thứ gì bạn đặt giữa thẻ mở và thẻ đóng của component sẽ được truyền vào dưới dạng props.children.
Modal không cần biết nội dung bên trong là gì — nó chỉ lo phần backdrop, khung trắng, và nút đóng. Nội dung là việc của component cha quyết định.
Viết Modal component
Modal.tsx
onClose được dùng ở hai chỗ: backdrop và nút X — cả hai đều chỉ gọi một hàm duy nhất từ cha truyền xuống, không tự quản lý state.
Conditional Rendering cho Modal đóng mở
isModalOpen là boolean — dùng nó để quyết định render Modal hay không. Có 3 cách phổ biến:
Cách 1 — Tách ra biến trước khi return
Dễ đọc nhất khi nội dung phức tạp:Cách 2 — Short-circuit &&
Gọn, phù hợp khi chỉ có một nhánh (true thì render, false thì không):
Cách 3 — Ternary operator
Dùng khi cần render khác nhau ở cả hai trạng thái:&& vì nếu điều kiện là false, biểu thức sẽ trả về giá trị false — không phải null.
TypeScript sẽ báo lỗi vì kiểu trả về đúng của component phải là JSX.Element | null, không phải boolean. Thay vào đó, hãy dùng ternary hoặc early return với null:
Conditional Rendering cho nút
Nút “New Post” cũng thay đổi trạng thái tùy theo modal đang mở hay đóng — dùng ternary để đổi text và disabled:PostList hoàn chỉnh
Ghép tất cả lại:PostList.tsx
Tóm tắt
Bài này kết hợp đủ các khái niệm đã học:useState— quản lýisModalOpen, form state, và list state.- State Lifting — tất cả state và handler đặt trong
PostList, truyền xuốngModalvàNewPostqua props. - Children Props —
Modalnhận nội dung linh hoạt quaprops.children, không cần biết bên trong là gì. - Conditional Rendering — 3 cách: biến
modalContent,&&, ternary — tùy độ phức tạp mà chọn.