CodeForge

React 19 de Cero a Experto / Routing

Parámetros de URL y query strings

Teoría20 min20 XP

Una misma vista sirve para muchos datos: /gastos/5 y /gastos/12 muestran el detalle de gastos distintos con el MISMO componente. La parte variable de la URL —el 5, el 12— es un PARÁMETRO de ruta, y tu componente lo lee con useParams. Y para filtros y estados que van en la URL sin ser una ruta nueva (?categoria=comida), están las query strings con useSearchParams. Hoy tu componente aprende a leer la parte dinámica de la dirección.

El número de habitación

Parámetros de ruta: useParams

Declaras el hueco variable con :nombre en el path, y lo lees con useParams:

useparams.tsx
import { Routes, Route, useParams } from "react-router-dom";

function App() {
return (
  <Routes>
    <Route path="/gastos" element={<ListaGastos />} />
    {/* :id es un hueco variable */}
    <Route path="/gastos/:id" element={<DetalleGasto />} />
  </Routes>
);
}

function DetalleGasto() {
// useParams devuelve los parámetros de la ruta actual (siempre strings)
const { id } = useParams();
// ojo: 'id' es string ("5"), conviértelo si necesitas número
const idNum = Number(id);
return <p>Mostrando el gasto #{idNum}</p>;
}

El :id en el path crea el parámetro; useParams() te lo entrega en un objeto ({ id }). Detalle importante: los parámetros SIEMPRE son strings —/gastos/5 te da id === "5", no 5—, así que conviértelos con Number(id) si esperas un número. Combinado con la carga de datos (TanStack Query del módulo 5), el patrón típico es: lees el id con useParams y lo usas como parte de la queryKey y la queryFn para cargar ese gasto.

Query strings: useSearchParams

Para filtros, orden, paginación o vistas —cosas que ajustan la MISMA página sin ser otra ruta— usas la query string (?categoria=comida), con useSearchParams (que se siente como un useState ligado a la URL):

usesearchparams.tsx
import { useSearchParams } from "react-router-dom";

function ListaGastos() {
const [params, setParams] = useSearchParams();
const categoria = params.get("categoria") ?? "todas"; // lee ?categoria=...

return (
  <div>
    <select
      value={categoria}
      onChange={(e) => setParams({ categoria: e.target.value })} // escribe en la URL
    >
      <option value="todas">Todas</option>
      <option value="comida">Comida</option>
      <option value="transporte">Transporte</option>
    </select>
    <p>Filtrando por: {categoria}</p>
  </div>
);
}

useSearchParams te da los parámetros de consulta (params.get("categoria")) y una función para cambiarlos (setParams), que actualiza la URL. La ventaja de poner el filtro en la URL en vez de en un useState: la vista se vuelve COMPARTIBLE y marcable —copias /gastos?categoria=comida y quien lo abra ve exactamente ese filtro—, y el botón atrás del navegador funciona sobre los filtros. La URL se convierte en parte del estado de tu UI.

Tienes una lista de gastos filtrable por categoría y una vista de detalle por gasto. ¿Dónde va cada dato en la URL?

Mini-reto

Diseña las rutas de una app de gastos: 1) /gastos/:id que lea el id con useParams, lo convierta a número y lo muestre; 2) en la lista /gastos, un filtro por categoría con useSearchParams que ponga ?categoria= en la URL; 3) verifica (en papel) que la URL /gastos?categoria=ocio es compartible y que /gastos/7 lleva al detalle correcto. Explica por qué el id es parámetro y la categoría es query.

Qué sigue

Ya lees la parte variable de la URL. Ahora, la estructura: casi toda app tiene partes que se REPITEN entre rutas —un menú lateral, un encabezado— mientras solo cambia el contenido central. La próxima lección trae los layouts anidados con <Outlet>: compartir estructura entre rutas sin repetirla.