![]()
Ở bài trước, chúng ta đã hiểu được "phép màu" của Expo Router: Chỉ cần tạo một file trong thư mục app/, chúng ta có ngay một đường dẫn (Route).
Nhưng hiện tại, các màn hình của chúng ta vẫn giống như những căn phòng bị khóa kín, không có cửa thông nhau. Làm thế nào để người dùng đang ở trang Home (danh sách nhân vật) bấm vào một mục và màn hình trượt mượt mà sang trang Detail? Và quan trọng hơn, làm sao trang Detail biết được người dùng vừa bấm vào nhân vật nào để hiển thị thông tin cho đúng?
Hôm nay, chúng ta sẽ mở toang những cánh cửa đó với Stack Navigation, cùng hai kỹ năng sống còn: Chuyển trang và Truyền tham số.
1. Stack Navigation là gì? Hiểu rõ về "Ngăn xếp"
Trong thế giới Mobile, cách phổ biến nhất để chuyển từ màn hình này sang màn hình khác được gọi là Stack Navigation (Điều hướng dạng Ngăn xếp).

Hãy tưởng tượng các màn hình của bạn giống như một xấp thẻ bài:
- Khi bạn mở app, bạn nhìn thấy lá bài đầu tiên (Trang Chủ).
- Khi bạn bấm vào một mục để xem chi tiết, ứng dụng sẽ lấy một lá bài mới (Trang Chi tiết) đặt đè lên trên lá bài Trang Chủ. Hành động này gọi là Push.
- Khi bạn nhấn nút "Back" (Quay lại) ở góc trái màn hình, ứng dụng sẽ vứt bỏ lá bài trên cùng đi, làm lộ ra lá bài Trang Chủ vẫn đang nằm chờ sẵn ở bên dưới. Hành động này gọi là Pop.
Nhờ cơ chế này, ứng dụng luôn ghi nhớ được "lịch sử" các trang bạn đã đi qua để có thể quay lại một cách chính xác.
2. Những cách chuyển trang trong Expo Router
Với Expo Router, việc "Push" một màn hình mới lên ngăn xếp dễ dàng đến mức đáng kinh ngạc. Có 2 công cụ chính để bạn làm việc này: Component <Link> và Hook useRouter.
Cách 1: Sử dụng Component Link (Dành cho giao diện tĩnh)
Nếu bạn đã biết làm Web, <Link> hoạt động y hệt thẻ <a>. Nó dùng để bọc một đoạn Text hoặc một nút bấm đơn giản.
Giả sử bạn có cấu trúc file:
app/index.tsx(Trang chủ)app/profile.tsx(Trang cá nhân)
Để đi từ Trang chủ sang Trang cá nhân, bạn viết code ở index.tsx như sau:
import { View, Text, StyleSheet } from 'react-native'
import { Link } from 'expo-router' // 1. Import Link
export default function HomeScreen() {
return (
<View style={styles.container}>
<Text>Đây là Trang Chủ</Text>
{/* 2. Sử dụng Link và truyền đường dẫn vào thuộc tính href */}
<Link href="/profile" style={styles.button}>
Đi tới Trang Cá Nhân
</Link>
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
button: { marginTop: 20, color: 'blue', fontSize: 18, fontWeight: 'bold' },
})
Cách 2: Sử dụng Hook useRouter (Dành cho xử lý Logic)
Component <Link> rất tốt, nhưng đôi khi bạn không muốn chuyển trang ngay lập tức. Ví dụ: Người dùng nhấn nút "Đăng nhập", bạn phải gọi API kiểm tra mật khẩu, nếu đúng thì mới chuyển trang. Lúc này, bạn cần Hook useRouter.
import { View, Text, TouchableOpacity } from 'react-native'
import { useRouter } from 'expo-router' // 1. Import useRouter
export default function LoginScreen() {
const router = useRouter() // 2. Khởi tạo router
const handleLogin = () => {
console.log('Đang kiểm tra mật khẩu...')
// Giả sử đăng nhập thành công
// 3. Sử dụng router.push() để chuyển trang
router.push('/home')
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity onPress={handleLogin} style={{ backgroundColor: 'green', padding: 15 }}>
<Text style={{ color: 'white' }}>Đăng Nhập</Text>
</TouchableOpacity>
</View>
)
}
Mẹo nhỏ: Nếu bạn muốn quay lại trang trước đó bằng code, chỉ cần gọi hàm router.back().
3. Truyền và nhận Tham số (Passing Params)
Đây là phần quan trọng nhất của bài viết. Chuyển trang thôi là chưa đủ, bạn phải mang theo dữ liệu!
Trở lại ví dụ: Từ màn hình Danh sách nhân vật, bạn bấm vào nhân vật "Katarina". Trang Chi tiết mở ra phải hiển thị đúng tên "Katarina" chứ không phải "Lee Sin". Ta làm điều này bằng cách truyền tham số (Params).
Bước 1: Gửi đi Tham số
Thay vì chỉ truyền một chuỗi đường dẫn đơn giản vào href hoặc router.push, chúng ta sẽ truyền một Object chứa thông tin pathname (đường dẫn) và params (dữ liệu mang theo).
// Gửi đi từ trang Danh Sách (app/index.tsx)
import { useRouter } from 'expo-router'
import { TouchableOpacity, Text } from 'react-native'
export default function ListScreen() {
const router = useRouter()
const goToDetails = () => {
// Chuyển sang trang details và mang theo id, name, role
router.push({
pathname: '/details',
params: { id: 1, name: 'Katarina', role: 'Sát thủ' },
})
}
return (
<TouchableOpacity onPress={goToDetails}>
<Text>Xem chi tiết Katarina</Text>
</TouchableOpacity>
)
}
Bước 2: Nhận lấy Tham số ở trang đích
Để "hứng" lấy những dữ liệu vừa được gửi tới, Expo Router cung cấp cho chúng ta một Hook cực kỳ mạnh mẽ tên là useLocalSearchParams.
// Nhận dữ liệu tại trang Chi tiết (app/details.tsx)
import { View, Text, StyleSheet } from 'react-native'
import { useLocalSearchParams } from 'expo-router' // 1. Import Hook
export default function DetailsScreen() {
// 2. Trích xuất các tham số được gửi tới
const { id, name, role } = useLocalSearchParams()
return (
<View style={styles.container}>
<Text style={styles.title}>Hồ sơ nhân vật số: {id}</Text>
<Text style={styles.info}>Tên: {name}</Text>
<Text style={styles.info}>Vai trò: {role}</Text>
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
title: { fontSize: 24, fontWeight: 'bold', color: 'red' },
info: { fontSize: 20, marginTop: 10 },
})
Lưu ý: Mọi tham số nhận được qua useLocalSearchParams() đều ở định dạng chuỗi (String). Nếu bạn truyền số 1, khi nhận lại nó sẽ là chuỗi "1".
4. Kỹ thuật nâng cao: Đường dẫn động (Dynamic Routes)
Ở những bài trước, chúng ta đã nhắc đến file có tên cặp ngoặc vuông [id].tsx. Hãy kết hợp nó với kỹ năng truyền tham số ở trên!

Thay vì tạo một file tĩnh là details.tsx, nếu bạn đặt tên file là app/details/[id].tsx, thư mục của bạn sẽ bắt được mọi đường dẫn có dạng /details/1, /details/2,...
Lúc này, bạn có thể truyền thẳng ID vào đường dẫn như làm web:
// Chuyển tới trang nhân vật có ID là 99
<Link href="/details/99">Xem nhân vật 99</Link>
Ở file app/details/[id].tsx, khi bạn gọi const { id } = useLocalSearchParams(), biến id sẽ tự động nhận giá trị là 99. Đây là chuẩn mực để làm các trang chi tiết sản phẩm, bài viết blog!
Kết luận: Cần phải làm chủ Stack Navigation
Ghi nhớ 3 công cụ cốt lõi của bài học hôm nay:
- Dùng
<Link>để chuyển trang ở các nút bấm tĩnh. - Dùng
useRouter()khi cần chuyển trang sau khi tính toán/gọi API. - Dùng
useLocalSearchParams()ở trang đích để lấy dữ liệu (params) được gửi đến.
Đến đây, bạn đã hoàn toàn làm chủ được việc luân chuyển giữa các trang theo dạng "Ngăn xếp" tiến - lùi. Nhưng hầu hết các ứng dụng hiện đại (như Facebook, Shopee, Tiktok) đều có một thanh Menu nằm ở dưới đáy màn hình để chuyển đổi nhanh giữa các tính năng chính.
Làm thế nào để tạo ra thanh Menu "quyền lực" đó? Câu trả lời sẽ có ở bài tiếp theo. Hãy đón xem nhé!