Kurs React Native · Moduł 3: Nawigacja
Stack Navigation - Podwodne Korytarze
W tej lekcji8
Witaj w korytarzach Atlantydy! Posejdon wprowadza cię w tajniki nawigacji - systemu, który pozwala przemieszczać się między ekranami aplikacji jak przez korytarze podwodnego pałacu.
Czym jest React Navigation?
React Navigation to najpopularniejsza biblioteka nawigacyjna dla React Native. Pozwala tworzyć różne typy nawigacji: stosową (Stack), zakładkową (Tab), szufladową (Drawer) i wiele innych.
Instalacja React Navigation w Expo
# Instalacja core
npx expo install @react-navigation/native
# Zależności dla 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
# Lub Native Stack (zalecany, szybszy)
npx expo install @react-navigation/native-stackPodstawowa konfiguracja
// App.tsx
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
// Definiujemy typy dla parametrów nawigacji
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: 'Pałac Atlantydy' }}
/>
<Stack.Screen
name="Details"
component={DetailsScreen}
options={{ title: 'Komnata Szczegółów' }}
/>
<Stack.Screen
name="Profile"
component={ProfileScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}Ekran główny z nawigacją
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}>Witaj w Atlantydzie!</Text>
{/* Nawigacja do ekranu bez parametrów */}
<Pressable
style={styles.button}
onPress={() => navigation.navigate('Details', {
itemId: 42,
title: 'Komnata Posejdona'
})}
>
<Text style={styles.buttonText}>Wejdź do komnaty</Text>
</Pressable>
{/* Użycie push zamiast navigate */}
<Pressable
style={styles.button}
onPress={() => navigation.push('Details', {
itemId: 43,
title: 'Komnata Trytona'
})}
>
<Text style={styles.buttonText}>Odkryj kolejną komnatę</Text>
</Pressable>
</View>
);
}Różnica między navigate a push
// navigate - jeśli już jesteś na tym ekranie, nic nie robi; w przeciwnym razie dodaje go na stos
// (od React Navigation 7 nie wraca do ekranu niżej na stosie, do tego służy popTo)
navigation.navigate('Details', { itemId: 1 });
// push - zawsze dodaje nowy ekran na stos (nawet jeśli taki sam)
navigation.push('Details', { itemId: 2 });
// Przykład: galeria obrazów gdzie każdy obraz otwiera Details
// push pozwala mieć wiele ekranów Details na stosieOdbieranie parametrów
type DetailsScreenProps = NativeStackScreenProps<RootStackParamList, 'Details'>;
function DetailsScreen({ route, navigation }: DetailsScreenProps) {
// Parametry są typowane dzięki RootStackParamList
const { itemId, title } = route.params;
return (
<View style={styles.container}>
<Text style={styles.title}>{title}</Text>
<Text>ID komnaty: {itemId}</Text>
{/* Powrót do poprzedniego ekranu */}
<Pressable onPress={() => navigation.goBack()}>
<Text>Wróć</Text>
</Pressable>
{/* Powrót do pierwszego ekranu na stosie */}
<Pressable onPress={() => navigation.popToTop()}>
<Text>Wróć do pałacu</Text>
</Pressable>
</View>
);
}Opcje nagłówka
<Stack.Screen
name="Details"
component={DetailsScreen}
options={({ route }) => ({
title: route.params.title,
headerStyle: {
backgroundColor: '#1a5276',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
// Przycisk w nagłówku
headerRight: () => (
<Pressable onPress={() => alert('Info!')}>
<Text style={{ color: '#fff', marginRight: 10 }}>ℹ</Text>
</Pressable>
),
})}
/>Dynamiczne opcje z navigation.setOptions
function DetailsScreen({ route, navigation }: DetailsScreenProps) {
const [count, setCount] = useState(0);
useEffect(() => {
// Dynamiczna zmiana tytułu
navigation.setOptions({
title: `Komnata #${route.params.itemId}`,
headerRight: () => (
<Text style={{ color: '#fff' }}>Odwiedziny: {count}</Text>
),
});
}, [navigation, route.params.itemId, count]);
return (
<View>
<Pressable onPress={() => setCount(c => c + 1)}>
<Text>Zwiększ licznik</Text>
</Pressable>
</View>
);
}Stack Navigation to podstawa nawigacji w React Native. Działa jak stos kart - każdy nowy ekran jest kładzieny na wierzch, a powrót zdejmuje górną kartę.
Kod do tej lekcji: 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}>Pałac Atlantydy</Text>
{/* Przejdź do ekranu 'Details' i przekaż parametr itemId */}
<Button
title="Wejdź do komnaty"
onPress={() => navigation.navigate('Details', { itemId: 42 })}
/>
</View>
);
}
function DetailsScreen({ route }) {
const { itemId } = route.params;
return (
<View style={styles.screen}>
<Text style={styles.title}>Komnata #{itemId}</Text>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
{/* TODO: dodaj <Stack.Navigator> z propem initialRouteName="Home" */}
{/* TODO: wewnątrz dodaj <Stack.Screen name="Home" component={HomeScreen} /> */}
{/* TODO: dodaj drugi <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',
},
});Hasła z dokumentacji w tej lekcji
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Co musi opakowywać całą nawigację w React Navigation?
2. Jaka jest różnica między navigation.navigate() a navigation.push()?
To 2 z 4 pytań do tej lekcji. Pozostałe rozwiążesz w grze.
Zadania praktyczne w grze
- Układanie w pionie
Uporządkuj elementy Stack Navigator od zewnętrznego do wewnętrznego:
- Klikanie w kolejności
Kliknij elementy w kolejności przekazywania parametrów do ekranu:
- Edytor kodu
Uzupełnij kod Stack Navigator.