Chuyển tới nội dung chính

Agent Skills - Phần 4: React Native Best Practices

Số lượt xem trang
Tóm tắt

Tài liệu tổng hợp React Native Best Practices dùng làm nguồn tham chiếu cho Agent Skills (ví dụ trong Cursor), bao gồm các chủ đề: Components, Styling, Navigation, State, Lists, Performance, Images, Forms, Touch, Animation, Async, Accessibility, Testing và Native modules. Mỗi guideline được đánh giá mức độ quan trọng và có ví dụ code cụ thể. Nội dung dựa trên bộ guideline từ ui-ux-pro-max-skill, giúp developers và AI Agents xây dựng ứng dụng React Native hiệu quả và tuân thủ best practices.

Tài liệu này tổng hợp React Native Best Practices dùng làm nguồn tham chiếu cho Agent Skills (ví dụ trong Cursor).
Nội dung dựa trên bộ guideline từ ui-ux-pro-max-skill — file react-native.csv.

Cập nhật: 08/02/2026.

Mức độ: 🔴 Cao · 🟡 Trung bình · 🟢 Thấp
Ví dụ code: + nên · - tránh


1. Components​

1.1 🟡 Use functional components​

React Native hiện đại chuẩn là function component + hooks.

  • Nên: Dùng functional component với hooks.
+ const App = () => { ... }
  • Không nên: Viết class component mới.
- class App extends Component { ... }

📖 Intro to React – React Native


1.2 🟡 Keep components small​

Áp dụng Single Responsibility Principle – mỗi component làm một việc rõ ràng.

  • Nên: Tách UI thành các component nhỏ: header, content, footer...
+ <Header />
+ <Content />
+ <Footer />
  • Không nên: Một component 500+ dòng xử lý mọi thứ.
- 500+ line component

1.3 🟡 Use TypeScript​

TypeScript giúp tránh bug runtime, tự hoàn thành tốt hơn.

  • Nên: Dùng TypeScript cho project mới, khai báo type cho props/state.
+ const Button: FC<Props> = () => { ... }
  • Không nên: Viết JS thuần không type.
- const Button = (props) => { ... }

1.4 🟢 Colocate component files​

File component nên đi cùng styles, test, v.v. trong cùng thư mục.

  • Nên: Dùng folder riêng cho mỗi component.
+ components/Button/index.tsx
+ components/Button/styles.ts
  • Không nên: Cấu trúc phẳng, styles rải rác ở nơi khác.
- components/Button.tsx
- styles/button.ts

2. Styling​

2.1 🔴 Use StyleSheet.create​

StyleSheet.create tối ưu hoá style object và cảnh báo typo.

  • Nên: Khai báo style bằng StyleSheet.create.
+ const styles = StyleSheet.create({
+ container: { padding: 16 },
+ });
  • Không nên: Tạo object style inline trong JSX.
- <View style={{ margin: 10 }} />

📖 StyleSheet – React Native


2.2 🟡 Avoid inline styles in render​

Inline style mỗi lần render tạo object mới, gây re-render không cần thiết.

  • Nên: Tham chiếu style từ styles.*.
+ <View style={styles.container} />
  • Không nên: Viết style object trực tiếp trong JSX.
- <View style={{ margin: 10, padding: 5 }} />

2.3 🟡 Use flexbox for layout​

Layout chính nên dùng flexbox thay vì absolute mọi nơi.

  • Nên: Dùng flexDirection, alignItems, justifyContent.
+ const styles = StyleSheet.create({
+ row: { flexDirection: 'row', alignItems: 'center' },
+ });
  • Không nên: Dựa vào position: 'absolute' để xếp layout.
- position: 'absolute' everywhere

📖 Flexbox – React Native


2.4 🟡 Handle platform differences​

Style đôi khi cần khác nhau cho iOS/Android.

  • Nên: Dùng Platform.select hoặc file .ios.tsx/.android.tsx.
+ const styles = StyleSheet.create({
+ container: Platform.select({
+ ios: { paddingTop: 44 },
+ android: { paddingTop: 0 },
+ }),
+ });
  • Không nên: Hard-code giá trị chỉ hợp với một platform.
- Hardcoded iOS values

📖 Platform-specific code


2.5 🟡 Use responsive dimensions​

UI phải scale tốt trên màn hình nhỏ/lớn khác nhau.

  • Nên: Dùng Dimensions hoặc useWindowDimensions.
+ const { width } = useWindowDimensions();
  • Không nên: Fix width height bằng pixel cố định cho toàn app.
- width: 375

3. Navigation​

3.1 🟡 Use React Navigation​

React Navigation là thư viện chuẩn cho routing trong React Native.

  • Nên: Dùng @react-navigation/* cho stack/tab/drawer.
+ const Stack = createStackNavigator();
  • Không nên: Tự implement state navigation thủ công.
- Custom navigation state

📖 React Navigation


3.2 🟡 Type navigation params​

Navigation nên được type-safe để tránh bug params.

  • Nên: Khai báo RootStackParamList và dùng generics.
+ navigation.navigate<RootStackParamList>('Home', { id });
  • Không nên: Gọi navigate với string thuần không type.
- navigation.navigate('Home', { id });

3.3 🟡 Support deep linking​

App nên hỗ trợ mở màn hình qua URL/deeplink.

  • Nên: Cấu hình prop linking cho React Navigation.
+ const linking = { prefixes: ['myapp://', 'https://myapp.com'] };
  • Không nên: Bỏ qua deep link, không cấu hình gì.
- No linking configuration

📖 Deep linking


3.4 🔴 Handle Android back button​

Back button trên Android cần được xử lý hợp lý (exit, pop stack...).

  • Nên: Dùng useFocusEffect + BackHandler.
+ useFocusEffect(
+ useCallback(() => {
+ const sub = BackHandler.addEventListener('hardwareBackPress', onBack);
+ return () => sub.remove();
+ }, [onBack]),
+ );
  • Không nên: Bỏ qua back button khiến UX tệ hoặc crash.
- No back handler

4. State​

4.1 🟡 Use useState for local UI state​

State UI đơn giản nên dùng useState.

  • Nên: Dùng useState cho counter, toggle, input...
+ const [count, setCount] = useState(0);
  • Không nên: Dùng class component với this.state cho case đơn giản.
- this.state = { count: 0 };

4.2 🟡 Use useReducer for complex state​

State có nhiều field liên quan hoặc logic phức tạp nên dùng useReducer.

  • Nên: Gom nhiều field liên quan vào reducer.
+ const [state, dispatch] = useReducer(reducer, initialState);
  • Không nên: 5+ useState cho các giá trị liên quan nhau.
- 5+ useState calls

4.3 🟡 Use context sparingly​

Context thích hợp cho theme/auth/locale – không cho dữ liệu đổi liên tục.

  • Nên: Dùng context cho theme, auth, locale...
+ <ThemeContext.Provider value={theme}>...</ThemeContext.Provider>
  • Không nên: Dùng context cho data list item thay đổi liên tục.
- Context for list item data

4.4 🟡 Consider Zustand or Redux for global state​

Global state phức tạp nên dùng riêng store, không prop drilling/useState khắp nơi.

  • Nên: Dùng Zustand cho đơn giản, Redux cho domain phức tạp.
+ const useStore = create((set) => ({ ... }));
  • Không nên: Dùng useState rồi prop drilling cho global state.
- Prop drilling global state

5. Lists​

5.1 🔴 Use FlatList for long lists​

List dài phải dùng FlatList (virtualized) thay vì ScrollView + map.

  • Nên: Dùng FlatList cho list > 50 items.
+ <FlatList data={items} renderItem={renderItem} />
  • Không nên: Map trực tiếp trong ScrollView.
- <ScrollView>{items.map(renderItem)}</ScrollView>

📖 FlatList


5.2 🔴 Provide keyExtractor​

Item trong list cần key ổn định, không dùng index.

  • Nên: Dùng keyExtractor với ID/stable key.
+ keyExtractor={(item) => item.id}
  • Không nên: Dùng index làm key.
- keyExtractor={(_, index) => index.toString()}

5.3 🔴 Optimize renderItem​

Item list nên được memo để tránh re-render không cần thiết.

  • Nên: Bọc item trong React.memo và dùng trong renderItem.
+ renderItem={({ item }) => <MemoizedItem item={item} />}
  • Không nên: Inline renderItem tạo View mới mỗi lần.
- renderItem={({ item }) => <View>...</View>}

5.4 🟡 Use getItemLayout for fixed-height rows​

List có item height cố định nên khai báo getItemLayout để tối ưu scroll.

  • Nên: Tính sẵn length và offset.
+ getItemLayout={(_, index) => ({
+ length: 50,
+ offset: 50 * index,
+ index,
+ })}
  • Không nên: Bỏ trống getItemLayout với list dài có fixed height.
- No getItemLayout for fixed height

5.5 🟡 Tune windowSize for large lists​

windowSize kiểm soát số item render quanh viewport.

  • Nên: Giảm windowSize cho list cực dài để tiết kiệm RAM.
+ <FlatList windowSize={5} ... />
  • Không nên: Dùng windowSize lớn mặc định cho list rất dài.
- windowSize={21} for huge lists

6. Performance​

6.1 🟡 Use React.memo for pure components​

Component chỉ phụ thuộc props nên memo để tránh re-render.

  • Nên: Export component với memo.
+ export default memo(MyComponent);
  • Không nên: Export component “trần”.
- export default MyComponent;

6.2 🟡 Use useCallback for handlers​

Handler truyền xuống child nên được useCallback để ổn định reference.

  • Nên: Memo hoá callback theo deps.
+ const handlePress = useCallback(() => { ... }, [deps]);
  • Không nên: Tạo function mới inline mỗi lần render.
- onPress={() => doSomething()}

6.3 🟡 Use useMemo for expensive calculations​

Tính toán nặng nên được cache bằng useMemo.

  • Nên: Dùng useMemo cho logic nặng phụ thuộc deps.
+ const result = useMemo(() => expensive(), [deps]);
  • Không nên: Gọi hàm nặng trực tiếp mỗi render.
- const result = expensive();

6.4 🟡 Avoid anonymous functions in JSX​

Anonymous function trong JSX tạo reference mới, khiến child re-render.

  • Nên: Truyền handler đã khai báo.
+ onPress={handlePress}
  • Không nên: Viết inline arrow function trong JSX.
- onPress={() => doSomething()}

6.5 🟡 Use Hermes engine​

Hermes giúp cải thiện startup time, memory và overall perf.

  • Nên: Bật Hermes trong cấu hình build.
+ hermes_enabled: true
  • Không nên: Dùng JavaScriptCore cho project mới mà không lý do.
- hermes_enabled: false

📖 Hermes


7. Images​

7.1 🟡 Prefer expo-image for modern image handling​

expo-image cung cấp caching, blur, performance tốt hơn cho RN (đặc biệt Expo).

  • Nên: Dùng expo-image cho list ảnh nặng.
+ <Image source={url} cachePolicy="memory-disk" />
  • Không nên: Dùng thư viện không maintain hoặc default Image cho case nặng.
- <FastImage source={url} />

📖 Expo Image


7.2 🔴 Specify image dimensions​

Ảnh remote cần width/height rõ để tránh flicker/layout shift.

  • Nên: Set width/height trong style.
+ <Image style={{ width: 100, height: 100 }} source={{ uri }} />
  • Không nên: Bỏ trống kích thước.
- <Image source={{ uri }} />

7.3 🟢 Use resizeMode​

resizeMode điều khiển cách ảnh được scale trong box.

  • Nên: Dùng cover, contain hoặc phù hợp use case.
+ <Image resizeMode="cover" ... />
  • Không nên: Bỏ resizeMode khiến mặc định không mong muốn.
- <Image ... />

8. Forms​

8.1 🟡 Use controlled inputs​

Form nên controlled (value + onChangeText) để state nhất quán.

  • Nên: Bind value vào state.
+ <TextInput value={text} onChangeText={setText} />
  • Không nên: Chỉ dùng defaultValue.
- <TextInput defaultValue={text} />

8.2 🔴 Handle keyboard properly​

Keyboard có thể che mất input/nút submit nếu không xử lý.

  • Nên: Dùng KeyboardAvoidingView cho form.
+ <KeyboardAvoidingView behavior="padding">
+ <Form />
+ </KeyboardAvoidingView>
  • Không nên: Bỏ qua, để keyboard che mất content.
- No keyboard handling

📖 KeyboardAvoidingView


8.3 🟢 Use proper keyboard types​

keyboardType nên khớp với loại input (email, number, phone...).

  • Nên: Dùng keyboard phù hợp.
+ <TextInput keyboardType="email-address" />
  • Không nên: Mọi input đều default.
- <TextInput keyboardType="default" />

9. Touch & Gestures​

9.1 🟢 Use Pressable for new touch interactions​

Pressable là API hiện đại, linh hoạt hơn TouchableOpacity.

  • Nên: Dùng Pressable cho touch interactions mới.
+ <Pressable onPress={handlePress}>...</Pressable>
  • Không nên: Tiếp tục thêm TouchableOpacity cho code mới.
- <TouchableOpacity onPress={handlePress}>...</TouchableOpacity>

📖 Pressable


9.2 🟡 Provide touch feedback​

Người dùng cần thấy feedback khi nhấn vào phần tử.

  • Nên: Dùng ripple (Android) hoặc opacity change.
+ <Pressable android_ripple={{ color: 'gray' }}>...</Pressable>
  • Không nên: Không có bất kỳ feedback nào khi bấm.
- No press feedback

9.3 🟡 Set hitSlop for small targets​

Icon nhỏ cần hitSlop để dễ bấm.

  • Nên: Tăng vùng chạm bằng hitSlop.
+ <Pressable hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>...</Pressable>
  • Không nên: Để touch target nhỏ < 44x44.
- 44x44 with no hitSlop

10. Animation & Gestures​

10.1 🟡 Use Reanimated for complex animations​

react-native-reanimated cho phép animation mượt trên UI thread.

  • Nên: Dùng Reanimated cho gesture/animation phức tạp.
+ const offset = useSharedValue(0);
  • Không nên: Dùng Animated API cũ cho flow gesture nặng.
- Animated.timing for gesture

📖 Reanimated


10.2 🔴 Run animations on UI thread​

Animation chạy trên UI thread sẽ mượt và không phụ thuộc JS thread.

  • Nên: Dùng worklet runOnUI.
+ runOnUI(() => { 'worklet'; /* animation */ })();
  • Không nên: Để animation nặng chạy trên JS thread.
- Animated on JS thread

10.3 🟡 Use gesture handler​

react-native-gesture-handler cho gesture native performant hơn JS onTouch*.

  • Nên: Dùng GestureDetector / gesture handler cho gesture phức tạp.
+ <GestureDetector gesture={gesture}>...</GestureDetector>
  • Không nên: Dùng onTouchMove JS cho mọi gesture.
- <View onTouchMove={...} />

📖 Gesture handler


11. Async Logic​

11.1 🟡 Handle loading states​

Async request nên có loading indicator rõ ràng.

  • Nên: Hiển thị ActivityIndicator trong khi chờ.
+ {isLoading ? <ActivityIndicator /> : <Content />}
  • Không nên: Để màn hình trống trong lúc load.
- No loading state

11.2 🔴 Handle errors gracefully​

Lỗi network/API cần UI hiển thị thông báo & retry, không crash app.

  • Nên: Có view lỗi rõ ràng.
+ {error ? <ErrorView /> : <Content />}
  • Không nên: Không handle error, để app crash hoặc treo.
- No error handling

11.3 🔴 Cancel async operations on unmount​

Async request/subscription cần cleanup để tránh memory leak.

  • Nên: Dùng AbortController hoặc return cleanup trong useEffect.
+ useEffect(() => {
+ const controller = new AbortController();
+ fetch(url, { signal: controller.signal });
+ return () => controller.abort();
+ }, [url]);
  • Không nên: Không cleanup subscription/timer.
- No cleanup for subscriptions

12. Accessibility​

12.1 🔴 Add accessibility labels​

Element interactive phải có accessibilityLabel mô tả hành động.

  • Nên: Thêm label rõ ràng cho button/icon.
+ <Pressable accessibilityLabel="Submit form">...</Pressable>
  • Không nên: Pressable không label.
- <Pressable>...</Pressable>

📖 Accessibility


12.2 🟡 Use accessibility roles​

accessibilityRole giúp screen reader hiểu loại control.

  • Nên: Gán role phù hợp (button, header, link...).
+ <Pressable accessibilityRole="button">...</Pressable>
  • Không nên: Không set role cho button/link.
- <Pressable>...</Pressable>

12.3 🔴 Test with screen readers​

App cần được test với TalkBack (Android) và VoiceOver (iOS).

  • Nên: Thường xuyên test luồng chính bằng screen reader.
+ Regular TalkBack testing
  • Không nên: Bỏ qua hoàn toàn accessibility testing.
- No screen reader testing

13. Testing​

13.1 🟡 Use React Native Testing Library​

Testing component nên dựa trên behavior (render, event) thay vì implementation.

  • Nên: Dùng @testing-library/react-native.
+ render(<Component />);
  • Không nên: Dùng Enzyme hoặc shallow rendering cũ.
- shallow(<Component />);

📖 React Native Testing Library


13.2 🔴 Test on real devices​

Simulator không phản ánh đầy đủ behavior (hiệu năng, gesture, camera...).

  • Nên: Test trên device thật cho cả iOS và Android.
+ Device testing in CI
  • Không nên: Chỉ test trên simulator/emulator.
- Simulator only testing

13.3 🟡 Use Detox for E2E​

Flow quan trọng nên có E2E test tự động.

  • Nên: Dùng Detox cho E2E của luồng chính.
+ detox test
  • Không nên: Chỉ test E2E bằng tay.
- Manual testing only

📖 Detox


14. Native & Permissions​

14.1 🔴 Use native modules carefully​

Bridge giữa JS và native có overhead – nên batch call.

  • Nên: Gom các native call, hạn chế gọi liên tục.
+ Batch updates
  • Không nên: Gọi native trên mọi keystroke/scroll nhỏ.
- Call native on every keystroke

14.2 🟢 Use Expo when possible​

Expo đơn giản hoá nhiều phần (build, permissions, camera, push...).

  • Nên: Dùng Expo nếu app không cần native custom quá phức tạp.
+ expo install package
  • Không nên: Dùng bare RN + manual linking cho app đơn giản.
- react-native link package

📖 Expo


14.3 🔴 Handle permissions correctly​

Permissions (camera, location, v.v.) phải được request/check đúng cách.

  • Nên: Dùng PermissionsAndroid (Android) hoặc API tương ứng, luôn check trước khi dùng.
+ const granted = await PermissionsAndroid.request(...);
  • Không nên: Truy cập tài nguyên trực tiếp mà không kiểm tra permission.
- Access without permission check

📖 PermissionsAndroid


Tóm tắt​

NhómSố guidelineMức độ ưu tiên
Components4🟢–🟡
Styling5🟡–🔴
Navigation4🟡–🔴
State4🟡
Lists5🟡–🔴
Performance5🟡
Images3🟢–🔴
Forms3🟡–🔴
Touch3🟢–🟡
Animation3🟡–🔴
Async3🟡–🔴
Accessibility3🟡–🔴
Testing3🟡–🔴
Native3🟢–🔴

Nguồn dữ liệu: react-native.csv — ui-ux-pro-max-skill.