React 19 de Cero a Experto / Routing
Parámetros de URL y query strings
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:
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):
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.