# Expo Router pour React Native : Guide Complet de la Navigation par Fichiers > Expo Router apporte le routage basé sur les fichiers à React Native, inspiré de Next.js. Guide complet avec configuration, navigation par onglets, routes dynamiques, modales, middleware et protection des routes. - Published: 2026-04-18 - Updated: 2026-04-18 - Author: SharpSkill - Tags: react-native, expo, expo-router, navigation, mobile-development, tutorial - Reading time: 9 min --- Expo Router transforme la gestion de la navigation dans les applications React Native en adoptant un système de routage basé sur les fichiers, directement inspiré de Next.js. Avec le SDK Expo 55 et Expo Router v6, la configuration manuelle des navigateurs appartient au passé. Il suffit de créer un fichier dans le répertoire `app` pour qu'un écran devienne accessible. Android, iOS et le web sont pris en charge de manière unifiée, sans configuration supplémentaire. Cette approche réduit considérablement la complexité des projets multiplateforme et accélère le développement mobile. > **Mise en route rapide** > > Les nouveaux projets Expo intègrent Expo Router par défaut. La commande `npx create-expo-app@latest --template default@sdk-55` génère un projet préconfiguré avec le routage par fichiers. Pour les projets existants, il suffit d'installer le package `expo-router` et de mettre à jour le point d'entrée de l'application. ## Fonctionnement du routage par fichiers dans Expo Router Chaque fichier placé dans le répertoire `app` devient automatiquement une route. Le chemin du fichier correspond directement au chemin de l'URL, ce qui élimine toute nécessité d'un fichier de configuration centralisé. Un fichier `app/settings.tsx` crée la route `/settings`, tandis que `app/profile/edit.tsx` correspond à `/profile/edit`. Cette convention offre trois avantages majeurs par rapport à la configuration traditionnelle avec React Navigation : - **Zéro configuration** : les routes existent dès la création du fichier - **Deep linking automatique** : chaque écran dispose d'une URL, facilitant le partage et les tests - **Navigation typée** : TypeScript connaît les routes existantes dès la compilation ```typescript // app/index.tsx import { View, Text, StyleSheet } from 'react-native' import { Link } from 'expo-router' export default function HomeScreen() { return ( Welcome {/* Link maps directly to file path */} Open Settings Edit Profile ) } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', padding: 24 }, title: { fontSize: 28, fontWeight: 'bold', marginBottom: 16 }, link: { fontSize: 16, color: '#61DAFB', marginTop: 12 }, }) ``` Le composant `Link` gère la navigation sur toutes les plateformes. Sur le web, il génère une balise ancre avec les attributs `href` appropriés pour le référencement. Sur les plateformes natives, il déclenche une navigation de type stack. ## Structure du projet et fichiers de layout Expo Router utilise des fichiers `_layout.tsx` pour définir les conteneurs de navigation. Chaque répertoire peut contenir son propre layout, créant ainsi des hiérarchies de navigation imbriquées. Le layout racine enveloppe l'ensemble de l'application, tandis que les layouts imbriqués contrôlent des sections spécifiques. Voici une structure de projet typique : ```text app/ _layout.tsx # Root layout (Stack or custom) index.tsx # Home screen (/) (tabs)/ # Tab group (parentheses = route group) _layout.tsx # Tab navigator home.tsx # /home tab search.tsx # /search tab profile.tsx # /profile tab settings/ _layout.tsx # Settings stack layout index.tsx # /settings notifications.tsx # /settings/notifications privacy.tsx # /settings/privacy ``` Les groupes de routes -- des répertoires entourés de parenthèses -- organisent les fichiers sans affecter l'URL. Le répertoire `(tabs)` ci-dessus crée un navigateur par onglets, mais les URL restent `/home`, `/search` et `/profile` plutôt que `/tabs/home`. ```typescript // app/_layout.tsx import { Stack } from 'expo-router' export default function RootLayout() { return ( ) } ``` Le layout racine sert également de point d'initialisation pour le chargement des polices, la configuration des providers et les réglages globaux. Il remplace le traditionnel `App.tsx` comme point d'entrée de l'application. ## Construction d'une navigation par onglets La navigation par onglets nécessite un fichier `_layout.tsx` à l'intérieur d'un groupe de routes. Expo Router v6 introduit `NativeTabs` pour des expériences natives spécifiques à chaque plateforme, mais le composant standard `Tabs` couvre la plupart des cas d'utilisation. ```typescript // app/(tabs)/_layout.tsx import { Tabs } from 'expo-router' import { Ionicons } from '@expo/vector-icons' export default function TabLayout() { return ( ( ), }} /> ( ), }} /> ( ), }} /> ) } ``` Chaque fichier d'écran d'onglet exporte un composant React standard. L'icône, le libellé et le badge de la barre d'onglets se configurent via la prop `options` du layout. ## Routes dynamiques et paramètres de route Les segments dynamiques utilisent des crochets dans le nom du fichier. Un fichier nommé `[id].tsx` correspond à un segment unique, tandis que `[...slug].tsx` capture tous les segments restants du chemin. ```typescript // app/product/[id].tsx import { View, Text, StyleSheet } from 'react-native' import { useLocalSearchParams, Stack } from 'expo-router' export default function ProductScreen() { // Extract the dynamic parameter from the URL const { id } = useLocalSearchParams<{ id: string }>() return ( Product Details ID: {id} ) } const styles = StyleSheet.create({ container: { flex: 1, padding: 24 }, heading: { fontSize: 24, fontWeight: 'bold', marginBottom: 8 }, id: { fontSize: 16, color: '#888' }, }) ``` Accéder à `/product/42` affiche cet écran avec la variable `id` définie sur `"42"`. Le hook `useLocalSearchParams` fournit un accès typé à l'ensemble des paramètres de route. Pour les routes attrape-tout, `[...slug].tsx` capture des segments de chemin entiers : ```typescript // app/docs/[...slug].tsx import { useLocalSearchParams } from 'expo-router' export default function DocsScreen() { // /docs/getting-started/installation → slug = ['getting-started', 'installation'] const { slug } = useLocalSearchParams<{ slug: string[] }>() return } ``` ## Typage des routes pour une sécurité à la compilation Expo Router génère automatiquement les types de routes lorsque la fonctionnalité `typed routes` est activée. Cette vérification détecte les liens cassés à la compilation plutôt qu'à l'exécution. Activation dans le fichier `app.json` : ```json { "expo": { "experiments": { "typedRoutes": true } } } ``` Une fois activé, la prop `href` du composant `Link` et l'argument de `router.push()` n'acceptent que des chaînes correspondant à des routes valides : ```typescript // app/checkout.tsx import { router } from 'expo-router' function handleCheckout(cartId: string) { // TypeScript validates this route exists router.push(`/product/${cartId}`) // This would cause a compile error if /nonexistent doesn't exist // router.push('/nonexistent') } ``` Le typage des routes fonctionne particulièrement bien avec `useLocalSearchParams`. Les types générés garantissent la correspondance entre les noms de paramètres dans la définition de la route et ceux utilisés par le composant consommateur, prévenant ainsi les bugs subtils qui ne se manifestent qu'à la navigation vers un écran spécifique. ## Écrans modaux et options de présentation Les modales dans Expo Router sont des écrans classiques configurés avec `presentation: 'modal'` dans le layout. Cette approche respecte la convention du routage par fichiers : une modale reste simplement une route comme les autres. ```typescript // app/_layout.tsx import { Stack } from 'expo-router' export default function RootLayout() { return ( {/* Modal screen slides up from the bottom */} ) } ``` ```typescript // app/create-post.tsx import { View, TextInput, Button, StyleSheet } from 'react-native' import { router } from 'expo-router' import { useState } from 'react' export default function CreatePostModal() { const [title, setTitle] = useState('') const handleSubmit = () => { // Submit logic here router.back() // Dismiss the modal } return (