1. 08:56 11/10/2026
Khi xây dựng các ứng dụng React đa nền tảng, việc xử lý file thường là một trong những tính năng phức tạp nhất. Người dùng mong đợi quy trình upload file mượt mà, hiển thị tiến trình rõ ràng và giao diện người dùng đồng nhất trên cả web và thiết bị di động. Dưới đây là hướng dẫn thực tế để xây dựng một hệ thống upload file có thể tái sử dụng, tận dụng các tính năng gốc của từng nền tảng trong khi vẫn giữ nguyên logic nghiệp vụ chung.
**1. Định nghĩa các kiểu dữ liệu chung**
Bắt đầu bằng việc tạo một thư mục shared types. Xác định một interface `UploadFile` bao gồm `name`, `size`, `type`, `uri` (cho React Native) hoặc `file` (cho web), và các trường `progress` và `status` (`pending`, `uploading`, `success`, `error`). Sử dụng các loại này trong cả hai dự án để tránh chuyển đổi không cần thiết.
**2. Xây dựng một custom hook cho logic upload cốt lõi**
Tạo `useUpload.ts` trong một package có thể tái sử dụng (hoặc trong thư mục hooks chung). Hook này nên chấp nhận một mảng file và một callback URL, sau đó trả về một đối tượng gồm các state như `files`, `progressMap`, `isUploading`, và các hàm `uploadAll`, `cancel`, `retry`. Bên trong hook, sử dụng `useCallback` để ghi đè các tác vụ upload khác nhau cho web (sử dụng `fetch` hoặc `axios`) và cho React Native (sử dụng `react-native-fs` hoặc `expo-file-system`).
**3. Tích hợp với quản lý state toàn cục**
Đối với các ứng dụng lớn, việc lưu trữ progress upload và danh sách file trong Redux Toolkit hoặc Zustand giúp đảm bảo tính đồng bộ giữa các component. Một slice `uploadSlice` đơn giản (Redux Toolkit) hoặc một store `useUploadStore` (Zustand) có thể lưu trữ cùng một dữ liệu mà custom hook sử dụng, giúp các component ở bất kỳ đâu cũng có thể theo dõi tiến trình.
**4. Xây dựng các thành phần UI có thể tái sử dụng**
Tạo một thư viện component (`@myapp/ui`) với các thành phần như `FileDropzone`, `ProgressBar`, và `FileList`. Sử dụng thư viện `react-dropzone` cho web và một thành phần thay thế tương tự cho React Native (ví dụ: `expo-document-picker`). Các component này nên nhận dữ liệu từ store chung, đảm bảo giao diện người dùng được đồng bộ.
**5. Thêm khả năng thử nghiệm**
Tận dụng React Testing Library và Jest để kiểm thử hook upload trên cả hai nền tảng. Sử dụng các helper `act` để mô phỏng quá trình upload, kiểm tra cập nhật progress, và xử lý lỗi. Việc thử nghiệm giúp đảm bảo rằng logic upload hoạt động chính xác khi chuyển đổi giữa các môi trường.
**6. Tối ưu hóa trải nghiệm người dùng**
- Hiển thị thông báo rõ ràng khi kéo thả file trên web.
- Sử dụng các chỉ dẫn trực quan trên thiết bị di động (ví dụ: nút "Chọn file từ thiết bị").
- Cho phép người dùng hủy hoặc thử lại các tác vụ upload đang chờ xử lý.
- Lưu trữ các file đã upload thành công trong bộ nhớ đệm (ví dụ: AsyncStorage cho React Native, IndexedDB cho web) để sử dụng lại trong các phiên làm việc sau.
Bằng cách tuân thủ các bước trên, bạn sẽ có một hệ thống upload file gọn gàng, có thể tái sử dụng, giúp giảm đáng kể lượng code trùng lặp và tăng tốc độ phát triển ứng dụng React đa nền tảng của bạn.