Đây không phải module chính của track ôn tập. Mục tiêu chỉ là giúp người mới có app chạy được, hiểu toolchain tối thiểu, và không kẹt ở lỗi setup trước khi học Module 01-03.
| Lớp | Nó làm gì? | Khi nào cần quan tâm? |
|---|---|---|
| JavaScript/TypeScript | Code UI, state, business logic. | Ngày nào cũng đụng. |
| Metro | Bundler đóng JS thành bundle để app native load. | Khi lỗi import, cache, asset, hot reload. |
| Native runtime | Android/iOS app shell chạy code RN. | Khi install native dependency, build release, permission. |
| Device/emulator | Môi trường thật để render UI và test gesture, network, storage. | Khi debug layout, performance, native behavior. |
| Lựa chọn | Nên dùng khi | Trade-off |
|---|---|---|
| Expo | App mới, muốn setup nhanh, học RN, cần thư viện phổ biến, muốn dùng EAS. | Dễ bắt đầu hơn, nhưng một số native use case cần config/plugin hoặc prebuild. |
| Community CLI | Dự án có native constraints rõ, tích hợp vào app native sẵn có, team kiểm soát Android/iOS sâu. | Setup nặng hơn, phải hiểu Android Studio/Xcode/CocoaPods nhiều hơn. |
Để học và làm playground, ưu tiên Expo. Khi đi làm, nhiều dự án RN vẫn dùng bare/CLI vì cần native module, build pipeline, signing, hoặc legacy setup. Biết cả hai mental model sẽ giúp debug tốt hơn.
npx create-expo-app@latest rn-first-app
cd rn-first-app
npm run android
# hoặc
npm run ios
# hoặc mở bằng Expo Go qua QR nếu project hỗ trợ
Sau khi chạy được, sửa màn hình đầu tiên thành ví dụ nhỏ:
import { useState } from 'react';
import { SafeAreaView, Text, Pressable, StyleSheet } from 'react-native';
export default function App() {
const [count, setCount] = useState(0);
return (
<SafeAreaView style={styles.screen}>
<Text style={styles.title}>RN First App</Text>
<Text style={styles.value}>Tap count: {count}</Text>
<Pressable style={styles.button} onPress={() => setCount(c => c + 1)}>
<Text style={styles.buttonText}>Increase</Text>
</Pressable>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
gap: 16,
backgroundColor: '#f8fafc',
},
title: {
fontSize: 28,
fontWeight: '700',
},
value: {
fontSize: 18,
},
button: {
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 8,
backgroundColor: '#2563eb',
},
buttonText: {
color: '#fff',
fontWeight: '700',
},
});
npx @react-native-community/cli@latest init RnBareApp
cd RnBareApp
npm run android
# macOS + Xcode setup đúng:
npm run ios
Nếu dùng CLI, hãy kiểm tra Android Studio, JDK, Xcode, CocoaPods theo docs chính thức. Đừng học RN bằng cách sửa bừa biến môi trường.
| Lỗi | Nguyên nhân hay gặp | Cách nghĩ để fix |
|---|---|---|
| Metro không load bundle | Terminal Metro chết, port bị chiếm, cache cũ. | Restart Metro, clear cache, kiểm tra app đang trỏ đúng dev server. |
| Android build fail | JDK/Gradle/SDK mismatch hoặc thiếu emulator. | Đọc dòng lỗi đầu tiên có nghĩa, không chỉ nhìn dòng cuối. |
| iOS build fail | Pod chưa install, Xcode version, signing, simulator runtime. | Phân biệt lỗi compile native với lỗi JS runtime. |
| App chạy nhưng màn hình trắng | JS exception, import sai, component return invalid. | Mở dev menu/log, xem console trước khi rebuild native. |
| Hot reload không ăn | Metro cache, file watcher, import cycle. | Save lại, reload app, restart bundler, sau cùng mới reinstall app. |
Trong dự án thật, lỗi setup thường không phải vì React Native khó, mà vì môi trường chưa khớp: Node version, JDK, Android SDK, Xcode, CocoaPods, env file, hoặc certificate. Cách xử lý tốt là xin checklist setup của team, chạy đúng version manager, rồi ghi lại lỗi/fix thành onboarding note.
Điểm phỏng vấn: đừng nói “em cài lại máy là được”. Hãy nói cách em phân loại lỗi: JS/Metro, native build, device runtime, config/env, network.
rn-first-app.