Implementando navegación avanzada con React Navigation y el uso de FlatList

En esta guía aprenderás cómo usar FlatList para renderizar una lista dinámica de datos con botones interactivos que permiten navegar entre pantallas, cómo tipar las rutas de un StackNavigator en React Navigation, y cómo acceder y personalizar los parámetros de navegación en una pantalla específica.


1. Configuración básica del StackNavigator con tipado

Primero, creamos un StackNavigator que incluye las pantallas de nuestra aplicación. En este caso, tiparemos las rutas utilizando TypeScript para asegurarnos de que los parámetros que pasemos entre pantallas sean estrictamente controlados.

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { HomeScreen } from '../screens/home/HomeScreen';
import { ProductsScreen } from '../screens/products/ProductsScreen';
import { SettingsScreen } from '../screens/settings/SettingsScreen';
import { ProductScreen } from '../screens/products/ProductScreen';

// Tipos para las rutas y sus parámetros
export type RootStackParams = {
  Home: undefined; // Sin parámetros
  Products: undefined; // Sin parámetros
  Product: { id: number; name: string }; // Parámetros requeridos
  Settings: undefined; // Sin parámetros
};

const Stack = createStackNavigator<RootStackParams>();

export const StackNavigator = () => {
  return (
    <Stack.Navigator
      screenOptions={{
        headerShown: true,
        headerStyle: {
          elevation: 0,
          shadowColor: 'transparent',
        },
      }}
    >
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Products" component={ProductsScreen} />
      <Stack.Screen name="Settings" component={SettingsScreen} />
      <Stack.Screen name="Product" component={ProductScreen} />
    </Stack.Navigator>
  );
};

Explicación:

  • RootStackParams: Define el tipo de las rutas y sus parámetros.
    • Por ejemplo, la pantalla Product espera recibir un objeto con las propiedades id y name.
  • createStackNavigator<RootStackParams>(): Tipamos el StackNavigator con los parámetros definidos.

2. Creando la pantalla de productos con FlatList

La pantalla ProductsScreen utiliza FlatList para renderizar dinámicamente una lista de productos, y cada producto tiene un botón para navegar a una pantalla específica (Product).

import React from 'react';
import { Text, View } from 'react-native';
import { globalStyles } from '../../theme/theme';
import { FlatList } from 'react-native-gesture-handler';
import { PrimaryButton } from '../../components/shared/PrimaryButton';
import { NavigationProp, useNavigation } from '@react-navigation/native';
import { RootStackParams } from '../../routes/StackNavigator';

const products = [
  { id: 1, name: 'Producto 1' },
  { id: 2, name: 'Producto 2' },
  { id: 3, name: 'Producto 3' },
  { id: 4, name: 'Producto 4' },
  { id: 5, name: 'Producto 5' },
  { id: 6, name: 'Producto 6' },
];

export const ProductsScreen = () => {
  const navigator = useNavigation<NavigationProp<RootStackParams>>();

  return (
    <View style={globalStyles.container}>
      <Text>ProductsScreen</Text>
      <FlatList
        data={products}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <PrimaryButton
            onPress={() => navigator.navigate('Product', item)}
            text={item.name}
          />
        )}
      />
      <Text>Ajustes</Text>
      <PrimaryButton
        onPress={() => navigator.navigate('Settings')}
        text="Ajustes"
      />
    </View>
  );
};

Explicación:

  1. FlatList:
    • data: La lista de productos que se va a renderizar.
    • keyExtractor: Genera claves únicas para cada elemento.
    • renderItem: Renderiza cada producto como un botón interactivo (PrimaryButton).
  2. Navegación con parámetros:
    • Al presionar un botón, se navega a la pantalla Product, pasando el objeto del producto (item) como parámetros.

3. Pantalla de producto (ProductScreen)

La pantalla ProductScreen recibe los parámetros id y name del producto seleccionado. También personalizamos el título del encabezado dinámicamente usando estos parámetros.

import { RouteProp, useNavigation, useRoute } from '@react-navigation/native';
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { Text } from 'react-native-paper';
import { RootStackParams } from '../../routes/StackNavigator';

export const ProductScreen = () => {
  const params = useRoute<RouteProp<RootStackParams, 'Product'>>().params;
  const navigation = useNavigation();

  useEffect(() => {
    // Personalizamos el título del header dinámicamente
    navigation.setOptions({
      title: params.name,
    });
  }, [navigation, params.name]);

  return (
    <View>
      <Text>ProductScreen</Text>
      <Text>{params.id} - {params.name}</Text>
    </View>
  );
};

Explicación:

  1. Acceso a los parámetros:
    • useRoute<RouteProp<RootStackParams, 'Product'>>(): Obtiene los parámetros tipados (id y name) para la ruta Product.
  2. Personalización del encabezado:
    • navigation.setOptions: Configura dinámicamente el título del encabezado (params.name).

4. Resumen sobre FlatList

FlatList es una herramienta poderosa para manejar listas en React Native. Algunos aspectos clave:

  • Es eficiente para manejar listas grandes, ya que solo renderiza los elementos visibles en la pantalla.
  • Soporta:
    • data: Los datos que se van a renderizar.
    • keyExtractor: Claves únicas para cada elemento.
    • renderItem: La función que renderiza cada elemento.
  • Es completamente personalizable, lo que la hace ideal para listas dinámicas con botones, imágenes u otros componentes.