React Native cho người đã biết React: những điểm cần làm quen

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Nếu bạn đã viết React cho web, bạn đã có sẵn khoảng một nửa kiến thức để làm ứng dụng di động bằng React Native. Nửa còn lại là những khác biệt về thành phần giao diện, cách tạo kiểu và cách chạy ứng dụng. Bài viết này chỉ ra các điểm đó để bạn đỡ bỡ ngỡ.

Những gì giữ nguyên

Component, props, state, hooks như useState hay useEffect, cách viết JSX và luồng dữ liệu một chiều đều giống hệt. Bạn vẫn chia giao diện thành các component nhỏ, vẫn dùng TypeScript, vẫn gọi API bằng fetch. Nhờ vậy việc học React Native chủ yếu là học thêm thư viện thành phần chứ không phải học lại tư duy.

Không còn thẻ HTML

Trên di động không có div, span hay p. Thay vào đó là các component cốt lõi do React Native cung cấp:

WebReact Native
divView
p, span, h1Text
imgImage
inputTextInput
buttonButton, Pressable
ul, li dàiFlatList

Quy tắc quan trọng: mọi chữ phải nằm trong thẻ Text. Nếu để chuỗi trần trong View, ứng dụng sẽ báo lỗi.

Tạo kiểu bằng StyleSheet

Không có CSS file hay class. Kiểu được viết bằng đối tượng JavaScript với tên thuộc tính dạng camelCase, và bố cục dựa trên Flexbox. Điểm khác web: chiều mặc định của flex là cột (column) chứ không phải hàng.

import { View, Text, StyleSheet } from 'react-native';

export default function Greeting({ name }: { name: string }) {
  return (
    <View style={styles.card}>
      <Text style={styles.title}>Xin chào, {name}</Text>
      <Text style={styles.sub}>Chào mừng bạn quay lại</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  card: {
    padding: 16,
    borderRadius: 12,
    backgroundColor: '#ffffff',
    margin: 12,
  },
  title: { fontSize: 20, fontWeight: '700' },
  sub: { marginTop: 4, color: '#666' },
});

Các đơn vị là số không có hậu tố (đơn vị độc lập mật độ điểm ảnh), không có px, rem hay %, trừ khi bạn dùng chuỗi phần trăm cho một số thuộc tính.

Xử lý chạm thay vì click

Thay vì onClick, hãy dùng Pressable hoặc các thành phần chạm có sẵn với sự kiện onPress. Pressable còn cho phép phản hồi khi nhấn giữ và đổi kiểu khi đang được nhấn.

<Pressable
  onPress={() => setCount(count + 1)}
  style={({ pressed }) => [styles.btn, pressed && { opacity: 0.6 }]}
>
  <Text>Bấm {count}</Text>
</Pressable>

Cuộn và danh sách

Trang web cuộn tự nhiên, còn trên di động bạn phải khai báo rõ vùng cuộn bằng ScrollView hoặc FlatList. Với danh sách dài hãy dùng FlatList vì nó chỉ vẽ các mục đang hiển thị, tiết kiệm bộ nhớ.

Điều hướng và thư viện

Không có trình duyệt nên không có URL như web. Điều hướng được xử lý bằng thư viện như React Navigation hoặc Expo Router. Nhiều khái niệm web như localStorage, window, document cũng không tồn tại; thay vào đó bạn dùng các thư viện như AsyncStorage hay SecureStore.

Môi trường chạy: Expo hay CLI?

Với người mới, Expo là cách khởi đầu nhanh nhất vì không cần cấu hình Android Studio hay Xcode ngay. Bạn có thể quét mã QR để xem ứng dụng trên điện thoại thật. Khi cần mô-đun native tùy biến, bạn vẫn có thể mở rộng sau.

Những sai lầm thường gặp của người từ web sang

  1. Cố dùng thẻ HTML hoặc thư viện chỉ chạy trên DOM.
  2. Quên rằng mỗi nền tảng có hành vi khác nhau, ví dụ bóng đổ, bàn phím, vùng an toàn của tai thỏ.
  3. Không kiểm thử trên thiết bị thật, chỉ xem trên máy ảo.
  4. Dùng ScrollView cho danh sách hàng nghìn mục.

Kết luận

Với nền tảng React, bạn chỉ cần thay bộ thành phần, học cách tạo kiểu mới và làm quen với điều hướng cùng quyền truy cập thiết bị. Hãy bắt đầu bằng một ứng dụng nhỏ rồi mở rộng dần, bạn sẽ thấy quá trình chuyển đổi nhanh hơn dự kiến.

Gọi API và quản lý state quen thuộc

Tin vui là phần lớn mã không phụ thuộc giao diện dùng lại được nguyên vẹn. Hook gọi dữ liệu bạn viết cho web gần như chạy ngay trên di động:

import { useEffect, useState } from 'react';

type Post = { id: number; title: string };

export function usePosts() {
  const [data, setData] = useState<Post[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((r) => r.json())
      .then((json) => { if (!cancelled) setData(json); })
      .catch(() => { if (!cancelled) setError('Không tải được dữ liệu'); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, []);

  return { data, loading, error };
}

Thư viện quản lý state như Redux Toolkit, Zustand hay TanStack Query cũng dùng được trên di động. Hãy tách riêng phần logic dùng chung thành các hook hoặc module thuần TypeScript, để nếu sau này bạn có cả ứng dụng web và di động, hai bên chia sẻ được phần lớn. Điểm cần cẩn trọng là phụ thuộc vào API trình duyệt như window hay localStorage trong các module dùng chung.

Nếu muốn đi theo một lộ trình có bài tập và dự án thực tế, bạn có thể xem các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment