Pelajari Expo Router 4 di React Native 2026: file-based routing, layout bersarang, typed routes, deep linking, dan migrasi bertahap dari React Navigation dengan contoh kode produksi.
Expo Router adalah sistem routing berbasis file untuk React Native yang otomatis membangun peta navigasi aplikasi dari struktur folder di direktori app/, mirip seperti Next.js App Router untuk web. Sejak versi 4 dirilis awal 2026, ia mendukung Server Components, typed routes yang lebih ketat, universal linking untuk web dan native, plus integrasi penuh dengan React Native New Architecture (Fabric + TurboModules). Panduan ini menunjukkan cara memigrasikan project React Navigation ke Expo Router, mengatur layout bersarang, deep linking, dan pola-pola produksi yang saya pakai sehari-hari.
Expo Router 4 memakai konvensi file-based routing: setiap file di dalam folder app/ otomatis menjadi rute, jadi tidak perlu konfigurasi Stack/Tab Navigator manual.
Layout bersarang (_layout.tsx) menggantikan pola NavigationContainer dan memungkinkan komposisi Stack, Tabs, serta Drawer secara deklaratif.
Typed routes (opsional via experiments.typedRoutes) memberikan autocomplete dan pengecekan tipe untuk semua path href di TypeScript.
Deep linking bekerja tanpa konfigurasi tambahan untuk URL kanonis; Anda hanya perlu menambahkan scheme di app.json kalau ingin custom scheme.
Expo Router mendukung Server Components dan Static Rendering untuk web, sehingga satu codebase bisa dipakai di iOS, Android, dan web yang SEO-friendly.
Migrasi dari React Navigation butuh pemetaan navigator manual ke struktur file, tetapi hook useRouter dan useLocalSearchParams mempermudah transisi kode navigasi imperatif.
Apa itu Expo Router dan kenapa penting di 2026?
Jadi, mari kita mulai dari dasarnya. Expo Router adalah framework routing universal yang dibangun di atas React Navigation, tetapi menghilangkan boilerplate konfigurasi navigator dengan pendekatan file-based. Alih-alih mendaftarkan setiap layar secara manual di dalam Stack.Navigator, Anda cukup membuat file di dalam folder app/ dan Expo Router akan otomatis membuat rute yang sesuai. Filosofinya sama dengan Next.js App Router di ekosistem web, jadi developer full-stack tidak perlu belajar dua paradigma berbeda.
Di 2026, Expo Router menjadi standar de facto untuk project baru berkat tiga alasan utama. Pertama, universal apps: satu file rute berjalan di iOS, Android, dan web tanpa duplikasi. Kedua, SEO-friendly. Expo Router 4 mendukung static rendering dan Server Components untuk target web, sehingga aplikasi React Native Anda dapat diindeks Google. Ketiga, developer experience yang jauh lebih enak, termasuk typed routes, autocomplete, dan hot reload yang lebih andal karena struktur file menjadi sumber kebenaran tunggal.
Perbedaan mendasar dengan pendekatan konvensional React Navigation adalah bahwa struktur folder menjadi struktur navigasi. File app/profile.tsx otomatis dapat diakses via /profile tanpa registrasi tambahan. Ini menghilangkan seluruh kategori bug "layar tidak ditemukan" yang sering muncul saat kita lupa mendaftarkan screen ke navigator (saya pernah menghabiskan tiga jam mengejar bug seperti ini di project e-commerce klien, dan setelah pindah ke Expo Router hal itu sama sekali tidak pernah terjadi lagi).
Instalasi dan setup project baru
Cara termudah memulai dengan Expo Router adalah menggunakan template resmi via create-expo-app. Template ini sudah menyiapkan struktur folder app/, konfigurasi babel.config.js, dan entry point yang dibutuhkan.
# Membuat project baru dengan template Expo Router
npx create-expo-app@latest my-app --template tabs
cd my-app
npm run start
Kalau Anda menambahkan Expo Router ke project existing, instal dependensi berikut dan sesuaikan konfigurasinya:
Aturan pemetaan file ke rute cukup lugas dan konsisten dengan konvensi framework modern. Setiap file dengan ekstensi .tsx, .jsx, .ts, atau .js di dalam app/ menjadi rute yang dapat diakses. Nama file menjadi segment URL, dan folder membentuk hierarki nested route.
Groups: folder dengan tanda kurung (auth) mengelompokkan rute untuk berbagi layout tanpa menambahkan segment URL. Ini berguna untuk memisahkan alur autentikasi dari main app.
Dynamic segments: kurung siku [id].tsx membuat parameter dinamis, sedangkan [...slug].tsx menangkap catch-all.
Layout files: _layout.tsx di setiap folder mendefinisikan navigator (Stack, Tabs, Drawer) yang membungkus rute anak.
Prefix +: file khusus seperti +not-found.tsx dan +html.tsx untuk konfigurasi platform-specific.
Root layout wajib ada dan berfungsi sebagai tempat inisialisasi provider global (theme, state management, error boundary). Contoh minimalnya seperti ini:
Kekuatan sesungguhnya Expo Router muncul saat Anda mengkombinasikan beberapa jenis navigator melalui layout bersarang. Setiap folder dapat memiliki _layout.tsx sendiri, dan navigator anak diwarisi dari parent secara alami.
Pola paling umum adalah tab bar utama yang berisi stack untuk setiap tab. Buat folder (tabs)/ dengan layout tabs, lalu di dalamnya letakkan folder per-tab yang punya stack sendiri:
Untuk kebutuhan drawer navigation di sisi tablet atau aplikasi konten berat, pakai Drawer dari expo-router/drawer dan bungkus dengan GestureHandlerRootView di root layout. Kombinasi layout seperti ini memungkinkan pola "drawer berisi tabs yang masing-masing berisi stack" tanpa satu baris pun konfigurasi navigator manual. Cukup rapi, kan?
Dynamic routes dan route parameters
Rute dinamis menggunakan sintaks kurung siku pada nama file. Nilai segment tersedia via hook useLocalSearchParams. Ini pola standar untuk halaman detail seperti profil pengguna atau artikel blog.
Untuk catch-all routes yang menangkap beberapa segment, pakai sintaks spread [...slug].tsx. Nilai slug akan berupa array string. Ini berguna untuk dokumentasi berjenjang atau breadcrumb kategori:
Query parameter juga otomatis ter-parse. Anda bisa memanggil router.push('/search?q=react') dan menerima { q: 'react' } di komponen tujuan. Untuk menghindari re-render berlebihan ketika hanya query yang berubah, pakai useLocalSearchParams alih-alih useGlobalSearchParams (perbedaannya subtle, saya jelaskan di FAQ bawah).
Navigasi imperatif dengan useRouter
Meski deklaratif via komponen <Link> adalah pola yang lebih disukai, kadang Anda perlu berpindah rute secara imperatif. Misalnya setelah submit form berhasil atau saat menerima push notification. Hook useRouter menyediakan API yang serupa dengan Next.js router.
import { useRouter, Link } from 'expo-router';
import { Button, View } from 'react-native';
export default function LoginScreen() {
const router = useRouter();
const handleLogin = async () => {
// ... panggil API login
router.replace('/(tabs)/home'); // ganti histori, bukan push
};
return (
<View>
<Button title="Masuk" onPress={handleLogin} />
<Link href="/register">Belum punya akun?</Link>
</View>
);
}
Metode yang tersedia meliputi router.push(), router.replace(), router.back(), dan router.dismissAll(). Yang terakhir itu sangat berguna untuk menutup semua modal stack dalam satu panggilan, pola umum setelah alur onboarding selesai.
Untuk pemahaman lebih dalam tentang manajemen state saat navigasi terjadi, silakan lihat panduan kami tentang state management React Native 2026 dengan Zustand. Kombinasi Zustand untuk state global dan Expo Router untuk navigasi terbukti sangat scalable di project produksi.
Deep linking dan universal links
Salah satu janji utama Expo Router adalah deep linking yang "just works". Karena setiap file adalah rute kanonis, URL seperti myapp://profile/42 otomatis membuka layar app/profile/[id].tsx tanpa konfigurasi tambahan. Anda hanya perlu mendefinisikan scheme di app.json.
Untuk universal links (iOS) dan App Links (Android), Anda tetap perlu hosting file apple-app-site-association dan assetlinks.json di server domain Anda. Dokumentasi deep linking resmi Expo memuat contoh JSON lengkap yang bisa disalin langsung.
Untuk test deep link di simulator, jalankan:
# iOS Simulator
xcrun simctl openurl booted "myapp://profile/42"
# Android Emulator
adb shell am start -a android.intent.action.VIEW -d "myapp://profile/42"
Typed routes dengan TypeScript
Salah satu fitur produktivitas terbaik di Expo Router 4 adalah typed routes eksperimental. Ketika diaktifkan, TypeScript akan tahu semua path valid di aplikasi Anda dan memberi error kalau Anda menautkan ke rute yang tidak ada atau lupa parameter wajib. Jujur, fitur ini yang akhirnya membuat saya mau memigrasikan project lama.
Aktifkan di app.json lalu jalankan npx expo start. File .expo/types/router.d.ts akan di-generate otomatis dan diperbarui setiap kali struktur file berubah.
// TypeScript akan flag error kompilasi berikut:
<Link href="/profil/42" /> // tidak ada rute /profil (typo)
<Link href="/profile" /> // rute butuh parameter [id]
<Link href="/profile/42" /> // valid
router.push({
pathname: '/profile/[id]',
params: { id: '42' },
}); // typed dan aman
Dalam project nyata, saya menyertakan .expo/types di tsconfig.json include array dan menambahkannya ke .gitignore supaya tidak menumpuk di history git. Manfaat produktivitasnya terasa dalam 1-2 minggu: refactor mengganti nama folder menjadi trivial karena TypeScript segera menampilkan semua link yang perlu diperbarui.
Migrasi dari React Navigation
Kalau Anda punya aplikasi React Navigation existing, migrasi bertahap sepenuhnya mungkin. Berikut pemetaan konsep utama yang saya pakai di beberapa migrasi klien:
React Navigation
Expo Router
createNativeStackNavigator()
Stack di _layout.tsx
createBottomTabNavigator()
Tabs di (tabs)/_layout.tsx
Stack.Screen name="Home" component={Home}
File app/home.tsx
navigation.navigate('Profile', { id })
router.push(`/profile/${id}`)
route.params.id
useLocalSearchParams()
navigation.setOptions({ title })
<Stack.Screen options={{ title }} />
linking config manual
Otomatis dari struktur folder
Langkah praktis migrasi bertahap: (1) instal expo-router, (2) buat folder app/ berdampingan dengan screens/ lama, (3) pindahkan satu tab atau satu flow ke Expo Router terlebih dahulu, (4) pakai useRouter di layar yang dimigrasikan sambil layar lama tetap pakai navigation.navigate. Setelah semua layar berpindah, hapus NavigationContainer lama dan file App.tsx utama karena Expo Router mengambil alih entry point.
Untuk pola animasi transisi kustom pasca-migrasi, artikel kami tentang React Native Reanimated 4 di Expo menunjukkan cara mengintegrasikan shared element transitions dengan Stack.Screen options.
Performa dan best practices produksi
Expo Router pada dasarnya efisien karena setiap layar dimuat malas (lazy) berdasarkan navigasi aktual, bukan diinisialisasi di awal seperti pola konvensional. Meski begitu, ada beberapa praktik yang saya rekomendasikan untuk performa optimal di aplikasi produksi:
Prefetch rute penting. Gunakan <Link prefetch> untuk layar yang kemungkinan besar dikunjungi setelah halaman saat ini (misal detail produk dari daftar produk). Prefetch memuat komponen di background sehingga transisi terasa instan.
Aktifkan Fabric / New Architecture. Set newArchEnabled: true di app.json. Expo Router 4 sepenuhnya kompatibel dan mendapat manfaat concurrent rendering React 19.
Jangan bungkus context provider besar di root layout. Bagi provider menjadi layer per-group. Provider state global boleh di root, tapi provider fitur (misal ChatProvider) sebaiknya di _layout.tsx folder terkait saja.
Pakai router.replace untuk navigasi post-auth. Hindari user bisa menekan back kembali ke layar login setelah berhasil masuk.
Static rendering untuk web. Kalau Anda deploy ke web, set web.output: "static" agar setiap rute jadi HTML terpisah yang SEO-friendly dan cepat dimuat.
Untuk detail lebih lanjut tentang membuat native modules yang berinteraksi dengan router, lihat panduan Expo Modules API dengan Swift dan Kotlin. Sinergi antara file-based routing dan modul native custom menjadi kombinasi kuat untuk aplikasi enterprise.
Terakhir, monitor performa navigasi dengan React Native DevTools yang sekarang sudah bawaan di React Native 0.76+. Tab "Profiler" menunjukkan berapa lama setiap layar butuh untuk mount, dan Anda dapat mengidentifikasi bottleneck seperti provider yang re-render berlebihan atau image tanpa lazy loading.
Pertanyaan yang Sering Diajukan
Apakah Expo Router menggantikan React Navigation?
Tidak sepenuhnya. Expo Router dibangun di atas React Navigation dan memakainya sebagai engine internal. Yang berubah adalah antarmukanya: Anda mendefinisikan rute via struktur file, bukan konfigurasi navigator manual. Semua fitur React Navigation (Stack, Tabs, Drawer, deep linking) tetap tersedia via komponen dan hook Expo Router.
Bisakah saya menggunakan Expo Router tanpa Expo?
Bisa. Meski dinamakan "Expo Router", library ini bekerja di project React Native bare (non-Expo). Anda perlu instal peer dependencies secara manual (react-native-safe-area-context, react-native-screens, expo-linking, expo-constants) dan set up entry point expo-router/entry. Beberapa modul Expo minor tetap dibutuhkan, tetapi Anda tidak perlu menggunakan Expo CLI atau EAS.
Apa perbedaan useLocalSearchParams dan useGlobalSearchParams?
useLocalSearchParams mengembalikan parameter hanya dari rute komponen tersebut dan tidak trigger re-render saat rute lain berubah. useGlobalSearchParams mengembalikan parameter dari rute apa pun yang aktif di stack, termasuk saat komponen sedang tersembunyi. Pakai useLocalSearchParams secara default untuk performa; pilih global hanya kalau Anda benar-benar butuh reaksi terhadap perubahan rute lain.
Bagaimana cara membuat rute yang dilindungi autentikasi?
Pola yang direkomendasikan adalah pakai folder group (app) untuk rute terautentikasi dan (auth) untuk login/register, lalu di root _layout.tsx pakai <Redirect> berdasarkan state autentikasi. Anda juga bisa memakai useRouter di dalam useEffect untuk redirect programatik. Sejak Expo Router 3.5+, komponen <Stack.Protected> menyederhanakan pola ini secara deklaratif.
Apakah Expo Router 4 mendukung React Server Components?
Ya, tapi masih eksperimental dan hanya untuk target web pada saat penulisan (Juli 2026). Aktifkan via experiments.reactServerComponents: true di app.json. Dukungan native (iOS/Android) sedang dalam roadmap dan diharapkan stabil di SDK 54. Untuk sekarang, pola yang lebih matang adalah pakai Static Rendering untuk konten SEO-critical.