Español

Explora patrones de navegación esenciales con React Router v6. Aprende sobre enrutamiento declarativo, rutas dinámicas, navegación programática, rutas anidadas y estrategias de carga de datos para construir aplicaciones web robustas y fáciles de usar.

React Router v6: Dominando los Patrones de Navegación para Aplicaciones Web Modernas

React Router v6 es una biblioteca de enrutamiento potente y flexible para aplicaciones React. Te permite crear aplicaciones de página única (SPAs) con una experiencia de usuario fluida al gestionar la navegación sin recargas de página completas. Esta publicación de blog profundizará en los patrones de navegación esenciales utilizando React Router v6, proporcionándote el conocimiento y los ejemplos para construir aplicaciones web robustas y fáciles de usar.

Comprendiendo los Conceptos Clave de React Router v6

Antes de sumergirnos en patrones específicos, repasemos algunos conceptos fundamentales:

1. Enrutamiento Declarativo con <Routes> y <Route>

La base de React Router v6 reside en el enrutamiento declarativo. Defines tus rutas usando los componentes <Routes> y <Route>. El componente <Routes> actúa como un contenedor para tus rutas, y el componente <Route> define una ruta específica y el componente a renderizar cuando esa ruta coincide con la URL actual.

Ejemplo: Configuración Básica de Rutas

Aquí hay un ejemplo básico de cómo configurar rutas para una aplicación simple:


import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

function App() {
  return (
    
      
        } />
        } />
        } />
      
    
  );
}

export default App;

En este ejemplo, definimos tres rutas:

El componente BrowserRouter habilita el enrutamiento basado en el historial del navegador. React Router compara la URL actual con las rutas definidas y renderiza el componente correspondiente.

2. Rutas Dinámicas con Parámetros de URL

Las rutas dinámicas te permiten crear rutas que pueden manejar diferentes valores en la URL. Esto es útil para mostrar contenido basado en un identificador único, como el ID de un producto o el ID de un usuario. React Router v6 utiliza el símbolo : para definir parámetros de URL.

Ejemplo: Mostrando Detalles del Producto

Supongamos que tienes una aplicación de comercio electrónico y quieres mostrar los detalles de cada producto según su ID. Puedes definir una ruta dinámica como esta:


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Obtener detalles del producto basados en productId
  // ...

  return (
    

Detalles del Producto

ID del Producto: {productId}

{/* Mostrar detalles del producto aquí */}
); } function App() { return ( } /> ); } export default App;

En este ejemplo:

Ejemplo de Internacionalización: Manejo de Códigos de Idioma

Para un sitio web multilingüe, podrías usar una ruta dinámica para manejar los códigos de idioma:


} />

Esta ruta coincidiría con URLs como /en/about, /fr/about y /es/about. El parámetro lang puede usarse para cargar los recursos de idioma apropiados.

3. Navegación Programática con useNavigate

Aunque el enrutamiento declarativo es excelente para enlaces estáticos, a menudo necesitas navegar programáticamente en función de las acciones del usuario o la lógica de la aplicación. React Router v6 proporciona el hook useNavigate para este propósito. useNavigate devuelve una función que te permite navegar a diferentes rutas.

Ejemplo: Redirección Después del Envío de un Formulario

Supongamos que tienes un formulario y quieres redirigir al usuario a una página de éxito después de que el formulario se envíe correctamente:


import { useNavigate } from "react-router-dom";

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Enviar los datos del formulario
    // ...

    // Redirigir a la página de éxito después de un envío exitoso
    navigate("/success");
  };

  return (
    
{/* Campos del formulario */}
); } export default MyForm;

En este ejemplo:

Pasar Estado Durante la Navegación

También puedes pasar estado junto con la navegación usando el segundo argumento de navigate:


navigate("/confirmation", { state: { orderId: "12345" } });

Esto te permite pasar datos al componente de destino, a los que se puede acceder usando el hook useLocation.

4. Rutas Anidadas y Diseños (Layouts)

Las rutas anidadas te permiten crear estructuras de enrutamiento jerárquicas, donde una ruta está anidada dentro de otra. Esto es útil para organizar aplicaciones complejas con múltiples niveles de navegación. Ayuda a crear diseños donde ciertos elementos de la interfaz de usuario están presentes de manera consistente en una sección de la aplicación.

Ejemplo: Sección de Perfil de Usuario

Digamos que tienes una sección de perfil de usuario con rutas anidadas para mostrar la información del perfil del usuario, la configuración y los pedidos:


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

Perfil de Usuario

  • Información del Perfil
  • Configuración
  • Pedidos
} /> } /> } />
); } function ProfileInformation() { return

Componente de Información del Perfil

; } function Settings() { return

Componente de Configuración

; } function Orders() { return

Componente de Pedidos

; } function App() { return ( } /> ); } export default App;

En este ejemplo:

El * en la ruta principal es crucial; significa que la ruta principal debe coincidir con cualquier sub-ruta, permitiendo que las rutas anidadas se correspondan correctamente dentro del componente Profile.

5. Manejo de Errores "No Encontrado" (404)

Es esencial manejar los casos en que el usuario navega a una ruta que no existe. React Router v6 facilita esto con una ruta comodín (catch-all).

Ejemplo: Implementando una Página 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - No Encontrado

La página que buscas no existe.

Volver al inicio
); } function App() { return ( } /> } /> } /> ); }

En este ejemplo:

6. Estrategias de Carga de Datos con React Router v6

React Router v6 no incluye mecanismos de carga de datos incorporados como su predecesor (React Router v5 con `useRouteMatch`). Sin embargo, proporciona las herramientas para implementar varias estrategias de carga de datos de manera efectiva.

Opción 1: Obteniendo Datos en los Componentes

El enfoque más simple es obtener los datos directamente dentro del componente que renderiza la ruta. Puedes usar el hook useEffect para obtener datos cuando el componente se monta o cuando cambian los parámetros de la URL.


import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";

function ProductDetails() {
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProduct() {
      try {
        const response = await fetch(`/api/products/${productId}`);
        if (!response.ok) {
          throw new Error(`¡Error HTTP! estado: ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Cargando...

; if (error) return

Error: {error.message}

; if (!product) return

Producto no encontrado

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Este enfoque es sencillo pero puede llevar a la duplicación de código si necesitas obtener datos en múltiples componentes. También es menos eficiente porque la obtención de datos comienza solo después de que el componente se ha montado.

Opción 2: Usando un Hook Personalizado para la Obtención de Datos

Para reducir la duplicación de código, puedes crear un hook personalizado que encapsule la lógica de obtención de datos. Este hook puede ser reutilizado en múltiples componentes.


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`¡Error HTTP! estado: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Luego, puedes usar este hook en tus componentes:


import { useParams } from "react-router-dom";
import useFetch from "./useFetch";

function ProductDetails() {
  const { productId } = useParams();
  const { data: product, loading, error } = useFetch(`/api/products/${productId}`);

  if (loading) return 

Cargando...

; if (error) return

Error: {error.message}

; if (!product) return

Producto no encontrado

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Opción 3: Usando una Biblioteca de Enrutamiento con Capacidades de Obtención de Datos (TanStack Router, Remix)

Bibliotecas como TanStack Router y Remix ofrecen mecanismos de obtención de datos incorporados que se integran perfectamente con el enrutamiento. Estas bibliotecas a menudo proporcionan características como:

Usar una biblioteca de este tipo puede simplificar drásticamente la carga de datos y mejorar el rendimiento, especialmente en aplicaciones complejas.

Renderizado del Lado del Servidor (SSR) y Generación de Sitios Estáticos (SSG)

Para mejorar el SEO y el rendimiento de la carga inicial, considera usar SSR o SSG con frameworks como Next.js o Gatsby. Estos frameworks te permiten obtener datos en el servidor o durante el tiempo de compilación y servir HTML pre-renderizado al cliente. Esto elimina la necesidad de que el cliente obtenga datos en la carga inicial, lo que resulta en una experiencia más rápida y amigable para el SEO.

7. Trabajando con Diferentes Tipos de Routers

React Router v6 proporciona diferentes implementaciones de router para adaptarse a diversos entornos y casos de uso:

Elige el tipo de router que mejor se adapte a los requisitos y al entorno de tu aplicación.

Conclusión

React Router v6 proporciona una solución de enrutamiento completa y flexible para aplicaciones React. Al comprender y aplicar los patrones de navegación discutidos en esta publicación de blog, puedes construir aplicaciones web robustas, fáciles de usar y mantenibles. Desde el enrutamiento declarativo con <Routes> y <Route> hasta rutas dinámicas con parámetros de URL, navegación programática con useNavigate y estrategias efectivas de carga de datos, React Router v6 te empodera para crear experiencias de navegación fluidas para tus usuarios. Considera explorar bibliotecas de enrutamiento avanzadas y frameworks de SSR/SSG para un control y una optimización del rendimiento aún mayores. Recuerda adaptar estos patrones a los requisitos específicos de tu aplicación y priorizar siempre una experiencia de usuario clara e intuitiva.

React Router v6: Dominando los Patrones de Navegación para Aplicaciones Web Modernas | MLOG