Cours React Native · Module 3: Navigation
Expo Router - La navigation moderne
Dans cette leçon10
Expo Router est un nouveau système de navigation révolutionnaire basé sur les fichiers, semblable à Next.js pour React Native !
Pourquoi Expo Router ?
- Routage basé sur les fichiers - la structure des dossiers = la structure de la navigation
- Deep Linking automatique - aucune configuration supplémentaire nécessaire
- Routes typées - prise en charge complète de TypeScript
- Support du web - fonctionne sur le web comme Next.js
- Lazy loading - les écrans sont chargés à la demande
Installation
# Nouveau projet avec Expo Router
npx create-expo-app@latest --template tabs
# Ou l'ajouter à un projet existant
npx expo install expo-router expo-linking expo-constantsConfiguration
// app.json
{
"expo": {
"scheme": "atlantis",
"web": {
"bundler": "metro"
},
"plugins": ["expo-router"]
}
}// package.json
{
"main": "expo-router/entry"
}Structure des fichiers = routage
app/
├── _layout.tsx # Layout racine
├── index.tsx # / (page d'accueil)
├── about.tsx # /about
├── settings/
│ ├── _layout.tsx # Layout pour /settings/*
│ ├── index.tsx # /settings
│ └── profile.tsx # /settings/profile
├── user/
│ └── [id].tsx # /user/123 (paramètre dynamique)
├── (tabs)/
│ ├── _layout.tsx # Tab Navigator
│ ├── home.tsx # Onglet Home
│ └── search.tsx # Onglet Search
└── +not-found.tsx # Page 404Layout racine
// app/_layout.tsx
import { Stack } from 'expo-router';
import { ThemeProvider } from '@/providers/ThemeProvider';
export default function RootLayout() {
return (
<ThemeProvider>
<Stack
screenOptions={{
headerStyle: { backgroundColor: '#0a2e4a' },
headerTintColor: '#fff',
}}
>
<Stack.Screen name="index" options={{ title: 'Atlantis' }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="user/[id]" options={{ title: 'Profil' }} />
</Stack>
</ThemeProvider>
);
}Page d'accueil
// app/index.tsx
import { View, Text, StyleSheet } from 'react-native';
import { Link } from 'expo-router';
export default function Home() {
return (
<View style={styles.container}>
<Text style={styles.title}>Bienvenue à Atlantis !</Text>
{/* Link en tant que composant */}
<Link href="/about" style={styles.link}>
À propos de l'application
</Link>
{/* Link avec des paramètres */}
<Link
href={{
pathname: '/user/[id]',
params: { id: '123' }
}}
style={styles.link}
>
Mon profil
</Link>
{/* Link vers le Tab Navigator */}
<Link href="/(tabs)/home" style={styles.link}>
Aller aux onglets
</Link>
</View>
);
}Routes dynamiques
// app/user/[id].tsx
import { useLocalSearchParams, useGlobalSearchParams, Stack } from 'expo-router';
export default function UserProfile() {
// Récupérer le paramètre depuis l'URL
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View>
{/* Titre dynamique */}
<Stack.Screen options={{ title: `Utilisateur #${id}` }} />
<Text>Profil de l'utilisateur : {id}</Text>
</View>
);
}Tab Navigator
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Ionicons } from '@expo/vector-icons';
export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: '#00d4ff',
tabBarStyle: { backgroundColor: '#0a2e4a' },
}}
>
<Tabs.Screen
name="home"
options={{
title: 'Accueil',
tabBarIcon: ({ color, size }) => (
<Ionicons name="home" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="search"
options={{
title: 'Recherche',
tabBarIcon: ({ color, size }) => (
<Ionicons name="search" size={size} color={color} />
),
}}
/>
</Tabs>
);
}Navigation par programmation
import { router } from 'expo-router';
function NavigationButtons() {
return (
<View>
{/* Naviguer vers un chemin */}
<Pressable onPress={() => router.push('/about')}>
<Text>À propos de l'application</Text>
</Pressable>
{/* Naviguer avec des paramètres */}
<Pressable onPress={() => router.push({
pathname: '/user/[id]',
params: { id: '456' }
})}>
<Text>Profil 456</Text>
</Pressable>
{/* Replace (sans possibilité de revenir en arrière) */}
<Pressable onPress={() => router.replace('/login')}>
<Text>Se déconnecter</Text>
</Pressable>
{/* Revenir en arrière */}
<Pressable onPress={() => router.back()}>
<Text>Retour</Text>
</Pressable>
{/* Vérifier si l'on peut revenir en arrière */}
{router.canGoBack() && (
<Pressable onPress={() => router.back()}>
<Text>Retour</Text>
</Pressable>
)}
</View>
);
}Groupes (masqués de l'URL)
// Les groupes entre parenthèses n'apparaissent pas dans l'URL
// app/(auth)/login.tsx → /login
// app/(tabs)/home.tsx → /home (et non /(tabs)/home)
// app/(auth)/_layout.tsx
import { Stack } from 'expo-router';
export default function AuthLayout() {
return (
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="login" />
<Stack.Screen name="register" />
</Stack>
);
}Expo Router est l'avenir de la navigation dans React Native. Il simplifie énormément le routage et gère automatiquement le Deep Linking !
Code de cette leçon : App.tsx
// Fichier : app/_layout.tsx (Expo Router - routage basé sur les fichiers)
import React, { useState } from 'react';
import { Stack, Redirect } from 'expo-router';
// Hook simple simulant l'état de connexion de l'utilisateur
function useAuth() {
const [isSignedIn] = useState(false);
return { isSignedIn };
}
export default function RootLayout() {
const { isSignedIn } = useAuth();
// TODO : si l'utilisateur N'est PAS connecté, redirige vers l'écran de connexion :
// if (!isSignedIn) {
// return <Redirect href="/login" />;
// }
// TODO : retourne un <Stack> qui masque l'en-tête pour le groupe (tabs) :
// <Stack>
// <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
// </Stack>
return null;
}Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Qu'est-ce que le routage basé sur les fichiers dans Expo Router ?
2. Que signifie le nom de fichier [id].tsx dans Expo Router ?
Voici 2 des 4 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Tri vertical
Range l'imbrication des layouts en partant de la racine :
- Éditeur de code
Complète le code de _layout.tsx.
- Tri horizontal
Range la récupération des paramètres dans Expo Router :