flutter-navegacion-declarativa-gorouter

Navegación declarativa en Flutter con go_router

  • 4 min

La navegación declarativa es describir qué ruta debe estar activa.

Hasta ahora hemos usado la Navegación Imperativa (Navigator.push). Es decir, nosotros “damos órdenes” manuales: “Pon esta pantalla encima”, “Quita esta pantalla”.

Esto funciona de maravilla para Apps sencillas. Pero, ¿qué pasa si estás haciendo una versión Web de tu App? Si el usuario escribe en la barra del navegador miapp.com/productos/15, con Navigator.push no tienes forma fácil de saber que tienes que ir directamente a esa pantalla.

Para resolver ese problema usamos Navegación Declarativa. En Flutter, una de las herramientas más habituales para esto es GoRouter.

El problema de la navegación imperativa

Imagina que tienes una notificación push. Cuando el usuario la toca, quieres llevarlo a la pantalla de “Detalle del Pedido”.

Si usas Navigator.push, tienes que reconstruir manualmente el camino:

  1. Ir al Home.
  2. Hacer push de la lista de pedidos.
  3. Hacer push del detalle.

Es propenso a errores y difícil de mantener. Además, no se sincroniza con la URL en la web.

Rutas nombradas

Flutter incluye un sistema nativo de rutas nombradas, aunque su documentación recomienda otras soluciones para la mayoría de aplicaciones con requisitos de navegación avanzados.

Consiste en definir un “mapa” de rutas en el MaterialApp:

// Enfoque válido, aunque con limitaciones
MaterialApp(
  routes: {
    '/': (context) => HomeScreen(),
    '/detalles': (context) => DetalleScreen(),
  },
);
Copied!

Y luego navegar usando nombres:

Navigator.pushNamed(context, '/detalles');
Copied!

¿El problema? Pasar argumentos es un dolor de cabeza (hay que extraerlos del ModalRoute) y no soporta bien “Deep Links” (enlaces profundos).

El paquete go_router

Para resolver estos escenarios, el ecosistema oficial de Flutter ofrece el paquete go_router.

GoRouter utiliza una navegación basada en URLs, incluso en el móvil.

  • Si quieres ir al inicio -> /
  • Si quieres ir a la configuración -> /settings
  • Si quieres ver el usuario 42 -> /users/42

¿Cómo funciona conceptualmente?

En lugar de apilar pantallas manualmente, defines un árbol de rutas. Cuando la URL cambia (ya sea porque tocaste un botón o escribiste en el navegador), GoRouter decide qué pantallas deben estar en la pila para coincidir con esa URL.

Es Declarativo: “Quiero estar en este estado”, en lugar de “Haz esto y luego esto”.

Un vistazo a la configuración

Para usarlo, necesitas añadir go_router a tu pubspec.yaml.

import 'package:go_router/go_router.dart';

// 1. Definimos la configuración
final _router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => HomeScreen(),
      routes: [
        // Ruta anidada: /details
        GoRoute(
          path: 'details',
          builder: (context, state) => DetailsScreen(),
        ),
      ],
    ),
  ],
);

void main() {
  runApp(MaterialApp.router(
    // 2. Conectamos GoRouter a la App
    routerConfig: _router,
  ));
}
Copied!

Lo bueno está en que movernos y pasar parámetros queda muy limpio:

// Ir a una página (Reemplaza la pila si es necesario)
context.go('/details');

// Pasar parámetros en la URL (ej: /users/123)
context.go('/users/$userId');
Copied!

Funciones de go_router

Estas son algunas de las funciones por las que resulta útil en aplicaciones con navegación compleja:

  1. Deep Linking: Si alguien te manda un enlace de WhatsApp miapp://oferta/50, GoRouter abre tu App y navega exactamente a esa pantalla automáticamente.
  2. Redirecciones (Guards): Puedes configurar lógica de seguridad. “Si el usuario intenta ir a /perfil pero no está logueado, redirígelo automáticamente a /login.
  3. Soporte Web: La barra de direcciones del navegador cambia a medida que navegas por la App.
  4. Parámetros de Ruta: Extraer el id de /product/:id es trivial (state.pathParameters['id']).

Qué enfoque usar

Sé que GoRouter puede parecer complejo de configurar al principio comparado con un simple Navigator.push. Aquí tienes mi recomendación para el curso:

  1. ¿Estás aprendiendo? Sigue usando Navigator.push (Imperativo). Es más fácil de entender al principio y suficiente para Apps pequeñas.
  2. ¿Necesitas web, enlaces profundos o redirecciones? Aprende go_router. Simplifica la sincronización con URLs y el acceso directo a rutas.