¿Quieres que tu app en React se comporte como una web de verdad, con rutas limpias, navegación fluida y sin recargas? En este artículo te explico qué es el routing en React, por qué se usa, y un ejemplo listo para copiar y pegar y que puedas ver cómo funciona. Vamos a ello.

¿Qué es el routing y por qué importa?

El routing es como un conserje en un hotel: según el número de habitación que le das (la URL), te dirige al cuarto correcto con su contenido. En las webs tradicionales cada URL apuntaba a un archivo HTML diferente; con esto funcionaba, pero tenía un problema: cada cambio de página implicaba una recarga de la página completa y un tiempo de espera que interrumpía la navegación del usuario.

Con React y una SPA (Single Page Aplication), el cliente (usuario con su navegador), puede descargar todos los archivos JavaScript de una sola vez, y una vez cargada la app, dejar que ella misma controle qué se muestra cuando la URL cambie. El resultado: navegación más rápida y fluida.

De multipage apps a SPA: ventajas y límites

Ventajas de una SPA con routing

  • Evitas recargas completas de página.
  • Conservas estados (por ejemplo: formularios parciales).
  • Transiciones más suaves.
  • Mejor experiencia de usuario.

Límites y retos

  • Necesitas gestionar el routing en el cliente.
  • Cuidado con el SEO si no haces prerender o SSR. Hoy en día Google ya indexa contenido cargado con JavaScript, por lo que una SPA con React Router no necesariamente necesita SSR o prerendering. Sin embargo, si buscas indexación rápida, compatibilidad con más buscadores, o un control SEO más fino, usar SSR o prerender sigue siendo una buena práctica.
  • En rutas profundas, puede faltar fallback del servidor si recargas la URL directamente, por ejemplo si accedes a una ruta «/producto/producto-123«, donde producto-123 no existe.

Por eso es importante usar herramientas bien pensadas como React Router, que ya maneja muchos de estos retos por ti.

Introducción a React Router

Al empezar a trabajar con React, la librería de por sí no trae soporte para routing. React se encarga de renderizar los componentes en pantalla, pero no tiene ni idea de qué hacer cuando el usuario cambia la URL o pulsa por ejemplo el botón de ir atrás en el navegador.

Podría por supuesto volverte loco y montarte tu propio sistema de escuchas URL con windows.history y popstate, pero tampoco vas a ponerte a solucionar algo que otros ya se encargaron de solucionar. Ya que para eso está React Router.

React Router es un librería estandarizada para hacer routing en React. Detecta cambios de URL, evita recargas innecesarias y renderiza el componente que toca sin que el usuario note que está navegando en una SPA.

Con React Router puedes:

  • Asociar URLs limpias (/productos, /carrito, /perfil) a componentes de React.
  • Controlar la navegación sin recargar toda la página.
  • Manejar parámetros dinámicos (/productos/:id).
  • Crear layouts reutilizables con cabeceras, menús o footers.
  • Definir páginas de error (404, 500).
  • Hacer redirecciones o navegación programática.

Hasta React Router v6 se usaba react-router-dom pero a partir de React Router v7, react-router-dom queda obsoleto. Ahora react-router integra todas las funcionalidad del DOM, NavLinks, rutas, etc.

Instalación y configuración básica

Para empezar deberás tener un proyecto en React con el que trabajar, si no sabes cómo: Instalación de React con Vite: Guía paso a paso

Cuando tengas un proyecto desde donde partir, instala el paquete de react-router

npm install react-router

y puedes estrcuturas tus archivos tal que así

src/
 ├─ components/
 │   └─ MainNavigation.jsx
 ├─ layouts/
 │   └─ RootLayout.jsx
 ├─ pages/
 │   ├─ Home.jsx
 │   ├─ Products.jsx
 │   ├─ ProductDetail.jsx
 │   └─ Error.jsx
 ├─ App.jsx
 ├─ main.jsx
 └─ index.css

añade a tu app.jsx:

import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import HomePage from './pages/Home';
import ProductsPage from './pages/Products';

const router = createBrowserRouter([
  { path: '/', element: <HomePage /> },
  { path: '/products', element: <ProductsPage /> },
]);

function App() {
  return <RouterProvider router={router} />;
}
export default App;

Vamos a ver qué está pasando aquí:

  • createBrowserRouter es la función que nos permite definir todas las rutas de la aplicación.
  • RouterProvider es el componente que se encarga de inyectar el router en la app para que React Router pueda escuchar los cambios de URL y renderizar el componente adecuado.

Con esto ya tendríamos dos rutas preparadas, habría por supuesto que crear tanto el componente HomePage como el ProductPage pero puedes crear un componente sencillo para cada una.

A createBrowserRouter le estamos pasando un array de objetos, donde cada objeto representa una ruta con su path (la URL) y su element (el componente que se va a mostrar).

Por último, dentro del componente App usamos <RouterProvider /> y le pasamos nuestro router como prop.

Ahora que ya tenemos rutas funcionando, toca lo más básico: poder navegar entre ellas. Y aquí hay un detalle importante: no uses <a href="…"> como lo harías en HTML de toda la vida.

¿Por qué? 🤔 Porque un <a> provoca una recarga completa de la página y no queremos eso. Eso implicaría:

  • que se vuelva a pedir todo al servidor
  • React se desmonta y se vuelve a montar desde cero.
  • adiós a los estados que tuvieras en memoria (carrito, formularios, etc…)

React Router trae su propio componente <Link>. Hace lo mismo que un <a>, pero con ciertos matices que lo hacen mejor aquí:

  • Evita la recarga completa (hace un preventDefault del click).
  • Cambia la URL directamente en el navegador.
  • Renderiza el componente correcto en función de tus rutas.

Se utiliza igual que <a> pero en vez de href, tiene que pasarle la URL a la prop to

<Link to="/products">Ir a productos</Link>

Hay veces en que quieres resaltar en el menú dónde estás (ejemplo: que “Productos” se ponga en negrita cuando estás en /products). Para eso existe <NavLink>.

Funciona igual que <Link>, pero te deja aplicar clases condicionales cuando la ruta está activa:

<NavLink
  to="/products"
  className={({ isActive }) => (isActive ? 'active' : undefined)}
>

Layouts y rutas anidadas

Ahora tienes tus componentes y por supuesto tienes varios de ellos que van a repetir en muchas páginas, header, menús, footer… la solución ingenua sería copiar y pegar ese código en cada componente… pero no. Vamos a usar los layouts y las rutas anidadas de React Router.

La idea es simple:

  1. Creas un componente RootLayout que tenga lo común (navegación, header, footer…).
  2. Le dices al router: “todas estas rutas van dentro de este layout”.
  3. React Router usará un <Outlet /> como hueco donde irá renderizando la página que toque.

Ejemplo de rutas con layout:

const router = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    children: [
      { path: '/', element: <HomePage /> },
      { path: '/products', element: <ProductsPage /> },
    ],
  },
]);

en este caso La ruta / y la ruta /products usan el mismo layout (RootLayout). Dentro de ese layout, en el sitio donde pongamos , se mostrará el componente correspondiente (Home o Products).

El layout RootLayout

import { Outlet } from 'react-router';
import MainNavigation from './components/MainNavigation';

function RootLayout() {
  return (
    <>
      <MainNavigation />
      <main>
        <Outlet />
      </main>
    </>
  );
}

export default RootLayout;
  • <MainNavigation /> se renderiza siempre, porque está fuera del <Outlet />.
  • <Outlet /> es el marcador de posición donde React Router inyectará la página hija (Home o Products en este caso).

Rutas dinámicas y useParams

Hasta ahora con tener nuestras rutas fijas tipo: /, /producto, etc. nos había ido bien, pero es probable que si tenemos productos tengamos una ruta como /producto/p1, /producto/p2

Para esto, react-router nos permite añadir rutas dinámicas, definiendo las variaciones de la url con «:» y variable, como por ejemplo:

{ path: '/products/:productId', element: <ProductDetailPage /> }

:productId actúa como una variable que cambiará según la URL.

Leyendo el parámetro con useParams()

Y dentro del componente que se carga al acceder a la ruta puedes acceder al valor de la url con el hook useParams() que trae React Router.

import { useParams } from 'react-router';

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

  return (
    <>
      <h1>Detalles del producto</h1>
      <p>ID del producto: {productId}</p>
    </>
  );
}

export default ProductDetailPage;

useParams() devuelve un objeto con todos los parámetros dinámicos de la URL. Puedes hacer destructuring, extraerlos y usarlos.

Haciendo esto va a poder mostrar todas las variaciones de página que quieras para una sola plantilla, solo cambiando el parámetro de la URL

Siguientes pasos y cierre

Hemos visto como con React Router, pasamos de tener componentes que cargabamos en una página, a una aplicación moderna, rápida y dinámica, donde la URL cambia sin que tu usuario lo note.

Lo bueno de React Router es que puedes empezar a usarlo desde ya, en cualquier página por muy sencilla que sea, empiezas con un par de rutas y, poco a poco, puedes añadir layouts, rutas protegidas, loaders de datos, etc.

Así que ya sabes: si quieres que tu SPA se sienta con la fluidez de una aplicación moderna, dale una oportunidad el routing con React Router.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *