Stack Navigator
Volver a clases
Desarrollo Móvil●Principiante

Stack Navigator

60 min

- 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}
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}

Recursos

1 recurso disponible

Reto de Lectura

Reto de LecturaPrincipiante60 min🟢 IA requerida

Auditoría IA #2 — La pantalla de lista con datos

Genera con tu IA una pantalla de lista con fetch y navegación al detalle, y audítala: performance de lista, async decorativo y params de navegación.

Paso 1 — Genera (10 min). Pídele a tu IA:

"Hazme en React Native con TypeScript una pantalla que cargue usuarios de https://jsonplaceholder.typicode.com/users, los muestre en una lista, y al tocar uno navegue a una pantalla de detalle con React Navigation, con manejo de errores"

Paso 2 — Audita (40 min):

#CapaPregunta clave
1Lista (S9)¿FlatList o ScrollView+map? ¿keyExtractor? ¿Estilos inline en renderItem?
2Async¿El catch traga o el error LLEGA a la pantalla (estado de error visible)? ¿Revisa response.ok? ¿Hay estado de loading?
3useEffect¿Dependencias honestas? ¿Qué pasa si navegas fuera antes de que llegue la respuesta?
4Navegación¿Qué viaja en los params: el id o el OBJETO usuario completo? ¿Qué implica cada opción si los datos se actualizan?
5Tipos¿Los params de las rutas están tipados o el navigate es as any?
6SabotajeSimula red lenta y toca un usuario ANTES de que cargue la lista de nuevo. Cambia la URL a una rota: ¿el usuario se entera?

Paso 3 — Informe (entregable): prompt, 4+ hallazgos con línea y escenario, corrección verificada en Snack/emulador con el sabotaje aplicado, veredicto de integración.

La solución no se publica. Se revisa en voz alta en el laboratorio, después de que trabajaste el reto. Trae tu diagnóstico escrito: eso es lo que se entrega.