Configurar rutas y parámetros entre pantallas

Video
25 min~8 min lectura

Reproductor de video

Configurar rutas y parámetros entre pantallas

En esta lección, nos adentraremos en el corazón de la experiencia de usuario de cualquier aplicación móvil: la navegación. Dominar la configuración de rutas y el paso de parámetros entre pantallas es lo que transforma una colección de componentes aislados en una aplicación cohesiva y fluida. Utilizaremos React Navigation, la librería estándar de facto en el ecosistema React Native, y nos enfocaremos en el stack de navegación, que es ideal para aplicaciones que requieren una jerarquía clara de pantallas, como un flujo de autenticación o una secuencia de detalles. Aprenderás no solo a moverte entre pantallas, sino a comunicar datos de manera eficiente y segura, un pilar fundamental para el desarrollo de aplicaciones nativas robustas.

Fundamentos de la Navegación con Stack Navigator

El Stack Navigator de React Navigation funciona bajo una metáfora muy intuitiva: una pila de cartas. Cada vez que navegas a una nueva pantalla, esta se coloca encima de la pila. Cuando presionas el botón de "atrás" (ya sea físico o en la cabecera), la pantalla superior se retira de la pila, revelando la anterior. Este modelo es perfecto para representar relaciones padre-hijo entre vistas, donde una pantalla conduce a otra con información más detallada. Configurar este navegador implica definir un conjunto de rutas, donde cada ruta está asociada a un componente de pantalla específico.

Para comenzar, es necesario instalar las bibliotecas requeridas. Con Expo, el proceso se simplifica enormemente. Necesitarás los paquetes @react-navigation/native y, para el stack específico, @react-navigation/stack, junto con sus dependencias físicas como react-native-screens y react-native-safe-area-context. Una vez instaladas, la configuración básica consiste en crear un componente NavigationContainer que envuelva toda tu aplicación y dentro, definir un Stack.Navigator que contenga tus Stack.Screen. Cada Screen recibe un name (el identificador de la ruta) y un component (el componente React a renderizar).

Tip: El NavigationContainer debe ser el ancestro más alto relacionado con la navegación en tu árbol de componentes. Es el encargado de gestionar el estado de navegación y vincular la cabecera superior con el gesto de retroceso del sistema.

Concepto Clave: Rutas, Parámetros y el Objeto de Navegación

Imagina que estás en una biblioteca (tu aplicación). Cada libro en un estante específico es una pantalla. La ruta sería la signatura topográfica del libro (ej: "Sección 5, Estante B, Libro 12"), un identificador único para encontrarlo. Los parámetros serían las anotaciones o marcadores que pasas de un libro a otro; por ejemplo, al leer un libro de historia que referencia un mapa en otro libro, le "pasas el parámetro" de la página del mapa para consultarlo rápidamente. En React Navigation, cada pantalla recibe un prop llamado navigation que contiene métodos para cambiar de ruta (como navigate o push) y un prop llamado route que contiene información sobre la ruta actual, incluyendo sus parámetros.

El método navigation.navigate('NombreDeRuta', { parametros }) es la forma principal de moverse. El primer argumento es el nombre de la ruta destino, definido en el Stack.Screen. El segundo argumento es un objeto opcional que puede contener cualquier dato serializable (números, strings, objetos, arrays) que quieras pasar a la pantalla destino. Allí, podrás acceder a estos datos mediante route.params. Esta comunicación unidireccional pero dinámica es lo que permite crear flujos de datos complejos, como pasar el ID de un usuario desde una lista a su perfil, o los datos de un producto a la pantalla de carrito.

Analogía: Piensa en navigation como el control remoto de tu TV (te permite cambiar de canal) y route.params como la información del programa que se está transmitiendo en el canal actual, que puede incluir datos extras enviados desde el canal anterior.

Cómo Funciona en la Práctica: Un Flujo de Detalles de Producto

Vamos a construir un ejemplo paso a paso común en aplicaciones de e-commerce: una lista de productos que al hacer tap en uno, navega a una pantalla de detalles con información específica. Primero, crea dos componentes de pantalla: ProductListScreen y ProductDetailScreen. En tu archivo de navegación principal (por ejemplo, AppNavigator.js), configura un Stack Navigator que registre ambas pantallas. Asegúrate de que el ProductListScreen sea la pantalla inicial.

Dentro de ProductListScreen, tendrás una lista de productos. Cada elemento de la lista (por ejemplo, un TouchableOpacity o Pressable) debe tener un manejador de evento onPress. En este manejador, llamarás a navigation.navigate('ProductDetail', { productId: item.id, productName: item.name }). Esto navegará a la pantalla de detalles y le pasará los parámetros productId y productName. En ProductDetailScreen, accederás a estos datos en el ciclo de vida del componente (por ejemplo, en un useEffect) o directamente en el renderizado mediante const { productId, productName } = route.params;. Con estos datos, puedes realizar una petición a una API para obtener los detalles completos o mostrarlos directamente.


// Ejemplo del manejador onPress en ProductListScreen
const handleProductPress = (product) => {
  navigation.navigate('ProductDetail', {
    id: product.id,
    title: product.title,
    price: product.price
  });
};

Código en Acción: Navegador Completo con Paso de Parámetros

A continuación, se presenta un ejemplo completo y funcional de un módulo de navegación con dos pantallas que demuestra la configuración, la navegación y el paso de parámetros de manera efectiva.


// App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{ title: 'Inicio' }}
        />
        <Stack.Screen
          name="Profile"
          component={ProfileScreen}
          options={({ route }) => ({ title: `Perfil de ${route.params?.userName || 'Usuario'}` })}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

// screens/HomeScreen.js
import React from 'react';
import { View, Button, Text } from 'react-native';

export default function HomeScreen({ navigation }) {
  const users = [
    { id: 1, name: 'Ana García', role: 'Admin' },
    { id: 2, name: 'Carlos López', role: 'Editor' },
    { id: 3, name: 'Marta Ruiz', role: 'Lector' }
  ];

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 24, marginBottom: 20 }}>Lista de Usuarios</Text>
      {users.map(user => (
        <View key={user.id} style={{ marginVertical: 10 }}>
          <Button
            title={`Ver perfil de ${user.name}`}
            onPress={() => navigation.navigate('Profile', {
              userId: user.id,
              userName: user.name,
              userRole: user.role
            })}
          />
        </View>
      ))}
      <Button
        title="Ir a Perfil sin Parámetros"
        onPress={() => navigation.navigate('Profile')}
      />
    </View>
  );
}

// screens/ProfileScreen.js
import React, { useEffect } from 'react';
import { View, Text, Alert } from 'react-native';

export default function ProfileScreen({ route, navigation }) {
  // Acceso seguro a los parámetros con valor por defecto
  const { userId, userName = 'Invitado', userRole = 'No especificado' } = route.params || {};

  useEffect(() => {
    // Ejemplo: Podrías hacer un fetch aquí usando el userId
    if (userId) {
      console.log(`Cargando datos del usuario con ID: ${userId}`);
      // fetchUserData(userId);
    } else {
      Alert.alert('Aviso', 'Se cargó el perfil sin un ID de usuario específico.');
    }
  }, [userId]);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 28, fontWeight: 'bold' }}>Pantalla de Perfil</Text>
      <View style={{ marginTop: 30, alignItems: 'center' }}>
        <Text>ID de Usuario: {userId ? userId : 'No proporcionado'}</Text>
        <Text>Nombre: {userName}</Text>
        <Text>Rol: {userRole}</Text>
      </View>
    </View>
  );
}

Errores Comunes y Cómo Evitarlos

1. Acceder a `route.params` sin verificar si es `undefined`: Este es el error más frecuente. Si navegas a una pantalla sin pasar parámetros, `route.params` será `undefined`. Intentar desestructurar o acceder a una propiedad de `undefined` causará un error fatal. Solución: Usa desestructuración con valores por defecto (`const { id } = route.params || {};`) o verifica con un operador condicional (`const userName = route.params?.userName;`).

2. Pasar parámetros no serializables: React Navigation requiere que los parámetros sean serializables en JSON. Pasar funciones, instancias de clase o componentes React causará advertencias y fallos. Solución: Pasa solo datos primitivos (string, number, boolean) o objetos/arrays compuestos por ellos. Si necesitas pasar lógica, considera usar un gestor de estado global (como Context o Redux) o un callback en la ruta mediante `setParams`.

3. Confundir `navigate` con `push`: `navigation.navigate('Ruta')` si ya estás en esa ruta, no hará nada (por defecto). `navigation.push('Ruta')` siempre añadirá una nueva instancia a la pila, incluso si es la misma pantalla. Usar `push` indiscriminadamente puede crear pilas infinitas. Solución: Usa `navigate` para movimientos principales y `push` solo cuando necesites múltiples instancias de la misma pantalla (ej.: comparar dos productos).

4. No configurar correctamente las opciones de pantalla dinámicas: Querer mostrar el nombre del usuario en el título de la pantalla de perfil es común, pero si se hace en la definición estática del `Screen`, no se actualizará. Solución: Usa la función `options` que recibe `({ route })` para definir opciones dinámicas, como se muestra en el ejemplo de `App.js` para la pantalla `Profile`.

5. Olvidar envolver la app con `NavigationContainer`: Sin este componente superior, la navegación no funcionará en absoluto. Solución: Asegúrate de que tu componente `App` exportado renderice el `NavigationContainer` en la raíz.

Checklist de Dominio

Antes de considerar que dominas esta lección, asegúrate de poder verificar los siguientes puntos:

  • Puedo instalar y configurar React Navigation (Stack) en un proyecto Expo desde cero.
  • Comprendo la diferencia entre `navigation` (acciones) y `route` (información) props.
  • Sé navegar a una pantalla usando `navigation.navigate('Ruta', { params })`.
  • Sé acceder de forma segura a los parámetros en la pantalla destino, manejando el caso `undefined`.
  • Puedo configurar opciones de pantalla estáticas (título fijo) y dinámicas (basadas en `route.params`).li>
  • Soy capaz de pasar objetos complejos pero serializables (ej.: un producto completo) entre pantallas.
  • He practicado el manejo del botón de "atrás" físico/gestual y entiendo la pila de navegación.
  • Puedo identificar y solucionar el error común de "Cannot read property 'X' of undefined" relacionado con `route.params`.
De lección a portfolio

Convertí esta lección en una habilidad visible para entrevistas.

Guardá el curso, completá los ejercicios y conectá esta habilidad con una ruta de empleo, data, IA, programación o marketing.

Newsletter Cursalo

Recibí rutas y cursos nuevos

Sumate para recibir recursos orientados a empleo y portfolio.

  • Rutas de empleo
  • Cursos prácticos
  • Portfolio y entrevistas

Sin spam. También podés entrar con tu cuenta para guardar progreso. Iniciá sesión