Core component
Core components
Không có div hay p. Bạn dùng View, Text, Image, TextInput, Pressable, FlatList. Mỗi cái được vẽ bằng view native thật.
From a clean Android setup to a tested React Native app built with Expo
Một trang, đi từ cài Android Studio và adb, qua dự án FocusList, đến test tự động bằng Maestro trên emulator.
Nếu bạn đã biết React cho web, bạn đã có 70% kiến thức. Phần còn lại là đổi bộ “gạch xây nhà”.
Core components
Không có div hay p. Bạn dùng View, Text, Image, TextInput, Pressable, FlatList. Mỗi cái được vẽ bằng view native thật.
Styling & layout
Style viết bằng object JS (backgroundColor, không phải background-color). Mọi thứ dàn bằng Flexbox, và hướng mặc định là dọc (column).
State & hooks
Giống hệt React web: useState, useEffect. Đổi state thì giao diện tự cập nhật.
Framework and toolchain
Expo là bộ công cụ và thư viện bao quanh React Native: tạo dự án, chạy thử, build, cập nhật. Nó giúp bạn khỏi phải tự cấu hình phần native.
File-based navigation
Giống App Router của Next.js: file trong thư mục app/ thành màn hình. app/add.tsx thành route /add.
Real devices & emulators
Code của bạn chạy bằng engine JS (Hermes) trong app native. Bạn xem kết quả trên điện thoại thật hoặc emulator Android.
| Web | React Native | Trên Android thành / Becomes on Android |
|---|---|---|
div | View | ViewGroup |
p, span, h1 | Text (chữ luôn phải nằm trong Text) | TextView |
img | Image | ImageView |
input | TextInput | EditText |
button, onclick | Pressable, onPress | View có nhận chạm |
ul + li | FlatList | Danh sách tái sử dụng view |
CSS px | Số không đơn vị = dp | density-independent pixel |
Bước này hay làm người mới nản nhất. Hãy chọn đúng mục tiêu để chỉ cài thứ bạn cần.
node -v).ANDROID_HOME và thêm thư mục công cụ vào PATH (dùng công cụ bên dưới).| Mục trong SDK Manager | Dùng để làm gì What for | Bắt buộc? |
|---|---|---|
| Android SDK Platform (một API level gần đây) | Thư viện để biên dịch app cho phiên bản Android đó | Có |
| Android SDK Platform-Tools | Chứa adb để nói chuyện với thiết bị | Có |
| Android SDK Build-Tools | Công cụ đóng gói APK/AAB, Gradle gọi tới | Có (khi build local) |
| Android Emulator | Chạy máy ảo | Nếu dùng emulator |
| System Image (đúng kiến trúc máy bạn) | “Hệ điều hành” cho máy ảo: x86_64 cho Intel/AMD, arm64 cho chip Apple Silicon | Nếu dùng emulator |
| Command-line Tools | Công cụ dòng lệnh như sdkmanager | Nên có |
Dự án React Native yêu cầu một bản JDK cụ thể (tài liệu hiện nay khuyên JDK 17, hãy kiểm tra lại cho phiên bản bạn dùng). JDK đi kèm Android Studio thường dùng được.
setx để sửa PATH trên Windows. Lệnh này có thể cắt ngắn PATH dài. Hãy sửa trong Environment Variables bằng giao diện rồi mở lại terminal.adb devices. Máy phải hiện trạng thái device.Tên menu thay đổi theo hãng máy (Samsung, Xiaomi, Oppo...).
adb cần nhớ adb cheat sheet| Lệnh | Công dụng |
|---|---|
adb devices | Liệt kê thiết bị và emulator đang kết nối |
adb reverse tcp:8081 tcp:8081 | Cho thiết bị nối tới Metro trên máy bạn qua cáp USB |
adb logcat *:E | Xem log lỗi của thiết bị |
adb install -r app.apk | Cài (hoặc cài đè) file APK |
adb shell pm clear com.example.focuslist | Xoá dữ liệu app, hữu ích để reset trước khi test |
adb shell input keyevent 82 | Mở menu nhà phát triển của app |
adb exec-out screencap -p > shot.png | Chụp màn hình thiết bị |
adb kill-server rồi adb start-server | Khởi động lại dịch vụ adb khi nó “đơ” |
| Triệu chứng | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
adb is not recognized | Chưa thêm platform-tools vào PATH | Thêm đường dẫn, mở lại terminal |
| SDK location not found | Thiếu ANDROID_HOME | Đặt biến, hoặc ghi sdk.dir=... vào android/local.properties |
Thiết bị hiện unauthorized | Chưa chấp nhận khoá RSA | Mở khoá máy, chấp nhận hộp thoại; nếu không có, thu hồi quyền gỡ lỗi USB rồi cắm lại |
| Emulator rất chậm hoặc không lên | Chưa bật ảo hoá, hoặc system image sai kiến trúc | Bật virtualization trong BIOS/OS, chọn image khớp CPU |
| App trắng/đỏ, không tìm thấy Metro | Thiết bị không thấy máy tính | adb reverse tcp:8081 tcp:8081, hoặc cùng Wi-Fi, hoặc npx expo start --tunnel |
| Gradle báo sai phiên bản Java | JAVA_HOME trỏ JDK khác | Trỏ tới JDK được yêu cầu (thường là JDK đi kèm Android Studio) |
| Port 8081 đã bị dùng | Có Metro khác đang chạy | Tắt tiến trình cũ hoặc chọn cổng khác khi chạy |
Công cụ chẩn đoán nhanh: npx expo-doctor kiểm tra cấu hình dự án Expo.
Bấm Bước tiếp hoặc Tự chạy để đi qua từng giai đoạn. Mặc định đang tạm dừng.
Sơ đồ khái niệm của kiến trúc mới, không theo tỉ lệ thời gian. Conceptual diagram, not to scale.
Thử thay đổi và so với mặc định của React Native.
Ứng dụng danh sách việc cần làm: xem danh sách, thêm việc mới, lưu lại trên máy. Dùng TypeScript và Expo Router.
| Tiêu chí | Expo Go | Development build | Bản phát hành (EAS) |
|---|---|---|---|
| Là gì | App có sẵn trên cửa hàng, nạp dự án của bạn | App riêng của bạn, kèm công cụ dev | Bản gửi lên cửa hàng |
| Thư viện native tuỳ chỉnh | Không | Có | Có |
| Cần Android Studio? | Không | Build trên máy: có. Build trên EAS: không | Không nếu build trên EAS |
| Dùng khi | Học, thử nhanh | Phát triển hằng ngày khi cần native | Phát hành, test E2E sát thực tế |
| File | Route | Ghi chú |
|---|---|---|
app/index.tsx | / | Màn hình đầu |
app/add.tsx | /add | Một màn hình khác |
app/task/[id].tsx | /task/42 | Đoạn động, đọc bằng useLocalSearchParams() |
app/_layout.tsx | (khung bọc) | Đặt Stack hoặc Tabs ở đây |
app/(tabs)/... | (nhóm route) | Ngoặc tròn nhóm file mà không đổi URL |
React Native dùng dp (density-independent pixel): cùng một số, kích thước nhìn gần như nhau trên mọi màn hình. Số pixel thật bằng dp nhân tỉ lệ mật độ.
Công thức: px = dp × density. Kích thước vật lý tính theo định nghĩa lý thuyết 1 dp = 1/160 inch. Thiết bị thật sai lệch nhất định. Trong code, PixelRatio.get() trả về tỉ lệ này.
Các ô đúng tỉ lệ với nhau về số pixel. Chúng không phải kích thước thật trên màn hình của bạn. 48 dp là cỡ tối thiểu thường được khuyến nghị cho vùng chạm trên Android (iOS thường nhắc 44 pt).
ScrollView vẽ tất cả phần tử một lúc, chỉ dùng cho nội dung ngắn.FlatList chỉ vẽ phần đang hiện và tái sử dụng view: luôn đặt keyExtractor.renderItem thành component riêng và bọc React.memo khi danh sách dài.Kiểm thử component nhanh, không cần emulator.
E2E (end-to-end) mở app thật trên emulator hoặc máy thật, rồi bấm như người dùng: đăng nhập, thêm việc, kiểm tra kết quả.
Minh hoạ, không theo tỉ lệ. Illustrative, not to scale. Quy tắc: viết ít E2E, chỉ cho các hành trình quan trọng (đăng nhập, thanh toán, thao tác chính).
Sơ đồ khái niệm, không theo tỉ lệ. Chi tiết bên trong từng công cụ khác nhau.
| Tiêu chí | Maestro | Detox | Appium |
|---|---|---|---|
| Cách viết test | File YAML | JavaScript/TypeScript với Jest | WebDriver, nhiều ngôn ngữ |
| Kiểu | Black-box | Gray-box, đồng bộ với app | Black-box |
| Cài đặt | Nhẹ, một CLI | Nặng hơn, phải cấu hình build native | Cần server và driver |
| Độ ổn định | Tự chờ giao diện ổn định | Tự đồng bộ với animation và mạng | Bạn thường tự viết đoạn chờ |
| Hợp với | Bắt đầu nhanh, QA ít code | Đội JS cần kiểm soát sâu | Đội đa ngôn ngữ, farm thiết bị |
Đánh giá chung, có thể thay đổi theo từng phiên bản. Hãy đọc tài liệu mới nhất trước khi chọn.
Chọn lệnh, nhập giá trị, bấm thêm. Mẫu YAML hiện ngay bên dưới.
Detox cần cấu hình build native (.detoxrc.js). Với Expo, bạn cần dev build và config plugin; hãy làm theo tài liệu hiện hành của Detox và Expo.
preview của EAS (đã đóng gói sẵn JS). Phiên bản action và cú pháp ở trên chỉ để minh hoạ, hãy kiểm tra lại.testID cho phần tử quan trọng; trên Android nó trở thành resource-id, trên iOS là accessibility identifier.clearState của Maestro hoặc adb shell pm clear.assertVisible), tránh sleep cố định.Kiến trúc cũ gửi thông điệp JSON bất đồng bộ qua “bridge”. Kiến trúc mới dùng JSI để JS gọi thẳng vào C++, cùng Fabric (vẽ giao diện) và TurboModules (module native nạp khi cần). Từ các bản gần đây nó là mặc định cho dự án mới, nhưng thời điểm và mức hỗ trợ kiến trúc cũ thay đổi giữa các bản, hãy xem ghi chú phát hành của phiên bản bạn dùng.
Thang đo đúng tỉ lệ: ms = 1000 ÷ fps, làm tròn. Muốn mượt, công việc cho mỗi khung hình phải xong trong ngần ấy thời gian.
Với Continuous Native Generation (CNG), thư mục android/ và ios/ được sinh ra từ app.json cộng các config plugin, nên bạn không phải commit code native.
React.memo, useCallback, useMemo ở nơi thật sự cần.console.log ồ ạt trong bản production.EXPO_PUBLIC_ được nhúng vào bundle JS và ai cũng đọc được, nên đừng đặt bí mật ở đó.expo-secure-store, không dùng AsyncStorage cho dữ liệu nhạy cảm.Mốc năm làm tròn và có thể lệch một chút tuỳ nguồn. Số phiên bản mới nhất của RN và Expo SDK thay đổi nhiều lần mỗi năm, hãy xem trang chính thức.
npx create-expo-app@latest và bật TypeScript strict.npx expo install để được bản tương thích với SDK.accessibilityLabel.TaskForm nhận onSubmit) để dễ test.testID ổn định ngay từ đầu cho các phần tử chính.npx expo-doctor và lint trong CI.| English | Tiếng Việt | Example sentence |
|---|
5 điểm mỗi câu đúng, từ câu đúng thứ 3 liên tiếp được thêm 2 điểm thưởng chuỗi. Điểm tối đa là 136.