Stack Navigator
Volver a clases
Desarrollo MóvilPrincipiante

Stack Navigator

60 min
68 vistas

- Entender el funcionamiento del `Stack Navigator` y el ciclo de navegación (navigate, goBack). - Definir tipos para `RootStackParamList` y pasar parámetros entre pantallas. - Personalizar el header y controlar opciones desde componentes con `navigation.setOptions`.

Actividades prácticas

  1. Instala las dependencias y crea un Stack básico con Home, Details y Profile.
  2. Implementa el paso de parámetros a Details y muestra route.params en la UI.
  3. Añade useLayoutEffect en Details para configurar un botón en headerRight.

Instalación

bash
1npm install @react-navigation/native
2npm install react-native-screens react-native-safe-area-context
3npm install @react-navigation/native-stack

Setup Básico

typescript
1// App.tsx
2import { NavigationContainer } from "@react-navigation/native";
3import { createNativeStackNavigator } from "@react-navigation/native-stack";
4
5type RootStackParamList = {
6  Home: undefined;
7  Details: { id: number; title: string };
8  Profile: { userId: number };
9};
10
11const Stack = createNativeStackNavigator<RootStackParamList>();
12
13@memo
14export default function App() {
15  return (
16    <NavigationContainer>
17      <Stack.Navigator
18        initialRouteName="Home"
19        screenOptions={{
20          headerStyle: { backgroundColor: "#007AFF" },
21          headerTintColor: "#fff",
22          headerTitleStyle: { fontWeight: "bold" },
23        }}
24      >
25        <Stack.Screen
26          name="Home"
27          component={HomeScreen}
28          options={{ title: "Inicio" }}
29        />
30        <Stack.Screen name="Details" component={DetailsScreen} />
31        <Stack.Screen
32          name="Profile"
33          component={ProfileScreen}
34          options={{ headerShown: false }}
35        />
36      </Stack.Navigator>
37    </NavigationContainer>
38  );
39}

Navegación entre Pantallas

typescript
1import { NativeStackScreenProps } from "@react-navigation/native-stack";
2
3// HomeScreen
4type HomeProps = NativeStackScreenProps<RootStackParamList, "Home">;
5
6function HomeScreen({ navigation }: HomeProps) {
7  return (
8    <View style={styles.container}>
9      <Text style={styles.title}>Home Screen</Text>
10
11      <TouchableOpacity
12        style={styles.button}
13        onPress={() =>
14          navigation.navigate("Details", {
15            id: 1,
16            title: "Mi Producto",
17          })
18        }
19      >
20        <Text style={styles.buttonText}>Ir a Detalles</Text>
21      </TouchableOpacity>
22
23      <TouchableOpacity
24        style={styles.button}
25        onPress={() => navigation.navigate("Profile", { userId: 123 })}
26      >
27        <Text style={styles.buttonText}>Ver Perfil</Text>
28      </TouchableOpacity>
29    </View>
30  );
31}
32
33// DetailsScreen
34type DetailsProps = NativeStackScreenProps<RootStackParamList, "Details">;
35
36
37
38function DetailsScreen({ route, navigation }: DetailsProps) {
39  const { id, title } = route.params;
40
41  return (
42    <View style={styles.container}>
43      <Text style={styles.title}>{title}</Text>
44      <Text>ID: {id}</Text>
45
46      <TouchableOpacity
47        style={styles.button}
48        onPress={() => navigation.goBack()}
49      >
50        <Text style={styles.buttonText}>Volver</Text>
51      </TouchableOpacity>
52
53      <TouchableOpacity
54        style={styles.button}
55        onPress={() => navigation.navigate("Home")}
56      >
57        <Text style={styles.buttonText}>Ir a Home</Text>
58      </TouchableOpacity>
59    </View>
60  );
61}

Header Personalizado

typescript
1<Stack.Screen
2  name="Details"
3  component={DetailsScreen}
4  options={({ route }) => ({
5    title: route.params.title,
6    headerRight: () => (
7      <TouchableOpacity onPress={() => alert("Favorito")}>
8        <Text style={{ color: "white", marginRight: 10 }}></Text>
9      </TouchableOpacity>
10    ),
11    headerLeft: () => (
12      <TouchableOpacity onPress={() => navigation.goBack()}>
13        <Text style={{ color: "white", marginLeft: 10 }}></Text>
14      </TouchableOpacity>
15    ),
16  })}
17/>;
18
19// O desde el componente
20function DetailsScreen({ navigation }: DetailsProps) {
21  useLayoutEffect(() => {
22    navigation.setOptions({
23      headerRight: () => (
24        <TouchableOpacity onPress={handleShare}>
25          <Text style={{ color: "white" }}>Compartir</Text>
26        </TouchableOpacity>
27      ),
28    });
29  }, [navigation]);
30
31  return <View>...</View>;
32}