Cours React Native · Module 3: Navigation

Stack Navigation - Les couloirs sous-marins

4 min de lecture ·
Dans cette leçon8

Bienvenue dans les couloirs d'Atlantis ! Poséidon te dévoile les secrets de la navigation : le système qui te permet de te déplacer entre les écrans de ton application comme à travers les couloirs d'un palais sous-marin.

Qu'est-ce que React Navigation ?

React Navigation est la bibliothèque de navigation la plus populaire pour React Native. Elle te permet de créer différents types de navigation : stack, tab, drawer, et bien d'autres.

Installer React Navigation dans Expo

# Installer le cœur
npx expo install @react-navigation/native

# Dépendances pour Expo
npx expo install react-native-screens react-native-safe-area-context

# Stack Navigator
npx expo install @react-navigation/stack
npx expo install react-native-gesture-handler

# Ou Native Stack (recommandé, plus rapide)
npx expo install @react-navigation/native-stack

Configuration de base

// App.tsx
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

// Définir les types des paramètres de navigation
type RootStackParamList = {
  Home: undefined;
  Details: { itemId: number; title: string };
  Profile: { userId: string };
};

const Stack = createNativeStackNavigator<RootStackParamList>();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{ title: 'Palais d\'Atlantis' }}
        />
        <Stack.Screen
          name="Details"
          component={DetailsScreen}
          options={{ title: 'Chambre des détails' }}
        />
        <Stack.Screen
          name="Profile"
          component={ProfileScreen}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Écran d'accueil avec navigation

import { NativeStackScreenProps } from '@react-navigation/native-stack';

type HomeScreenProps = NativeStackScreenProps<RootStackParamList, 'Home'>;

function HomeScreen({ navigation }: HomeScreenProps) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Bienvenue à Atlantis !</Text>

      {/* Navigation vers un écran sans paramètres */}
      <Pressable
        style={styles.button}
        onPress={() => navigation.navigate('Details', {
          itemId: 42,
          title: 'Chambre de Poséidon'
        })}
      >
        <Text style={styles.buttonText}>Entrer dans la chambre</Text>
      </Pressable>

      {/* Utilisation de push au lieu de navigate */}
      <Pressable
        style={styles.button}
        onPress={() => navigation.push('Details', {
          itemId: 43,
          title: 'Chambre de Triton'
        })}
      >
        <Text style={styles.buttonText}>Découvrir la chambre suivante</Text>
      </Pressable>
    </View>
  );
}

Différence entre navigate et push

// navigate - si tu es déjà sur cet écran, il ne fait rien ; sinon il l'ajoute à la pile
// (depuis React Navigation 7, il ne revient plus à un écran plus bas dans la pile, utilise popTo pour cela)
navigation.navigate('Details', { itemId: 1 });

// push - ajoute toujours un nouvel écran à la pile (même s'il est identique)
navigation.push('Details', { itemId: 2 });

// Exemple : galerie d'images où chaque image ouvre Details
// push permet d'avoir plusieurs écrans Details sur la pile

Recevoir les paramètres

type DetailsScreenProps = NativeStackScreenProps<RootStackParamList, 'Details'>;

function DetailsScreen({ route, navigation }: DetailsScreenProps) {
  // Les paramètres sont typés grâce à RootStackParamList
  const { itemId, title } = route.params;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title}</Text>
      <Text>ID de la chambre : {itemId}</Text>

      {/* Revenir à l'écran précédent */}
      <Pressable onPress={() => navigation.goBack()}>
        <Text>Retour</Text>
      </Pressable>

      {/* Revenir au premier écran de la pile */}
      <Pressable onPress={() => navigation.popToTop()}>
        <Text>Retour au palais</Text>
      </Pressable>
    </View>
  );
}

Options de l'en-tête

<Stack.Screen
  name="Details"
  component={DetailsScreen}
  options={({ route }) => ({
    title: route.params.title,
    headerStyle: {
      backgroundColor: '#1a5276',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
    // Bouton dans l'en-tête
    headerRight: () => (
      <Pressable onPress={() => alert('Info!')}>
        <Text style={{ color: '#fff', marginRight: 10 }}>ℹ</Text>
      </Pressable>
    ),
  })}
/>

Options dynamiques avec navigation.setOptions

function DetailsScreen({ route, navigation }: DetailsScreenProps) {
  const [count, setCount] = useState(0);

  useEffect(() => {
    // Changer dynamiquement le titre
    navigation.setOptions({
      title: `Chambre #${route.params.itemId}`,
      headerRight: () => (
        <Text style={{ color: '#fff' }}>Visites : {count}</Text>
      ),
    });
  }, [navigation, route.params.itemId, count]);

  return (
    <View>
      <Pressable onPress={() => setCount(c => c + 1)}>
        <Text>Augmenter le compteur</Text>
      </Pressable>
    </View>
  );
}

Stack Navigation est le fondement de la navigation dans React Native. Elle fonctionne comme une pile de cartes : chaque nouvel écran se pose au sommet, et revenir en arrière retire la carte du dessus.

Code de cette leçon : App.tsx
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function HomeScreen({ navigation }) {
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>Palais de l'Atlantide</Text>
      {/* Navigue vers l'écran 'Details' et transmets le paramètre itemId */}
      <Button
        title="Entrer dans la chambre"
        onPress={() => navigation.navigate('Details', { itemId: 42 })}
      />
    </View>
  );
}

function DetailsScreen({ route }) {
  const { itemId } = route.params;
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>Chambre #{itemId}</Text>
    </View>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      {/* TODO : ajoute un <Stack.Navigator> avec la prop initialRouteName="Home" */}
      {/* TODO : à l'intérieur, ajoute <Stack.Screen name="Home" component={HomeScreen} /> */}
      {/* TODO : ajoute un second <Stack.Screen name="Details" component={DetailsScreen} /> */}

    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#1a5276',
    gap: 16,
  },
  title: {
    fontSize: 22,
    color: '#fff',
    fontWeight: '600',
  },
});

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. 1. Qu'est-ce qui doit englober toute la navigation dans React Navigation ?

  2. 2. Quelle est la différence entre navigation.navigate() et navigation.push() ?

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 les éléments du Stack Navigator du plus externe au plus interne :

  • Clique dans l'ordre

    Clique sur les éléments dans l'ordre pour passer des paramètres à un écran :

  • Éditeur de code

    Complète le code du Stack Navigator.

Articles utiles