Parámetros en React Router con useParams
Introducción al problema
Hasta ahora tenemos el listado de ofertas funcionando con React Router, pero hay algo clave que falta: no podemos entrar al detalle de una oferta concreta.
Ahora mismo:
- ✅ Vemos un listado de trabajos
- ✅ Podemos navegar por algunas rutas
- ❌ Pero no existe una página de detalle para cada oferta
Eso significa que aunque tengamos el id de cada trabajo, no lo estamos usando en la URL para cargar la información específica de esa oferta.
En esta clase vamos a:
- Crear una página de detalle para una oferta
- Definir una ruta dinámica que reciba un parámetro (la id)
- Usar el hook
useParamsde React Router para leer esa id desde la URL
Qué son los parámetros de ruta
En una URL como:
/jobs/1234
/jobses la ruta base1234es un parámetro dinámico: la id de la oferta
React Router nos permite definir rutas que no son fijas, sino que incluyen segmentos variables que luego podemos leer:
/jobs/:id
:ides un placeholder- Cuando naveguemos a
/jobs/abc, el parámetroidserá"abc" - Cuando naveguemos a
/jobs/42, el parámetroidserá"42"
El objetivo es capturar ese valor para poder:
- Pedir los detalles a la API
- Mostrar el contenido específico de esa oferta
Creando la página de detalle
Primero creamos un nuevo componente para el detalle de la oferta.
// src/pages/JobDetail.jsx
export function JobDetail() {
return <h1>Job detail</h1>
}
De momento solo muestra un texto genérico.
Luego lo iremos mejorando con la id y, más adelante, con los datos reales.
Definiendo la ruta dinámica con :id
Ahora vamos a crear una ruta que reciba una id dinámica.
En el archivo donde definimos las rutas (por ejemplo App.jsx o router.jsx):
import { Route, Routes } from 'react-router'
import { JobDetail } from './pages/JobDetail'
export function App() {
return (
<Routes>
{/* Otras rutas */}
<Route path="/jobs/:id" element={<JobDetail />} />
</Routes>
)
}
Puntos clave
path="/jobs/:id":idindica que esa parte de la URL es un parámetro dinámico
element={<JobDetail />}- Cuando la URL coincida con
/jobs/algo, se renderizaJobDetail
- Cuando la URL coincida con
Prueba en el navegador
- Ve a
/jobs/1 - Ve a
/jobs/jajajata - Ve a
/jobs/1234
En todos los casos se renderiza la misma página, pero con diferentes valores de id en la URL.
Leyendo los parámetros con useParams
Ahora queremos que JobDetail pueda leer la id de la URL.
React Router nos da el hook useParams para esto:
// src/pages/JobDetail.jsx
import { useParams } from 'react-router'
export function JobDetail() {
const params = useParams()
console.log(params)
return (
<>
<h1>Job detail</h1>
<pre>{JSON.stringify(params, null, 2)}</pre>
</>
)
}
Si visitas /jobs/jajajata, verás algo así en la consola:
{ "id": "jajajata" }
Y si visitas /jobs/1234:
{ "id": "1234" }
Desestructurando el parámetro
Normalmente desestructuramos directamente el parámetro:
import { useParams } from 'react-router'
export function JobDetail() {
const { id } = useParams()
return (
<>
<h1>Job detail</h1>
<h2>La ID es: {id}</h2>
</>
)
}
Puntos importantes
useParams()devuelve un objeto- Cada clave del objeto corresponde al nombre del parámetro en la ruta
- Todos los valores son strings, aunque parezcan números
El nombre del parámetro manda
Un error muy típico es pensar que el parámetro siempre se llama id.
En realidad, el nombre depende de lo que tú pongas en la ruta.
Si defines la ruta así:
<Route path="/jobs/:jobId" element={<JobDetail />} />
Entonces useParams() devolverá:
{ "jobId": "1234" }
Y en el componente tendrás que hacer:
export function JobDetail() {
const { jobId } = useParams()
return (
<>
<h1>Job detail</h1>
<h2>La ID es: {jobId}</h2>
</>
)
}
Resumen
- Si la ruta es
"/jobs/:id"→useParams()devuelve{ id } - Si la ruta es
"/jobs/:jobId"→useParams()devuelve{ jobId }
El nombre del parámetro tiene que coincidir exactamente entre:
- Lo que pones en el
path(:id,:jobId,:slug, etc.) - Lo que desestructuras desde
useParams()
Usando la ID para pedir datos a la API
Aunque en un principio solo mostramos la id en pantalla, el siguiente paso natural es usarla para pedir datos reales.
Por ejemplo:
import { useEffect, useState } from 'react'
import { useParams } from 'react-router'
export function JobDetail() {
const { id } = useParams()
const [job, setJob] = useState(null)
useEffect(() => {
if (!id) return
fetch(`/api/jobs/${id}`)
.then((res) => res.json())
.then((data) => {
setJob(data)
})
.catch((error) => {
console.error('Error cargando el job', error)
})
}, [id])
if (!job) {
return <p>Cargando oferta...</p>
}
return (
<section>
<h1>{job.title}</h1>
<p>{job.description}</p>
<p>Ubicación: {job.location}</p>
</section>
)
}
Conceptos clave
- La id viene de la URL, no de props: Esto hace que el componente sea independiente
- Si el usuario recarga la página, la id sigue estando en la URL: La información no se pierde
- Esto hace que la app sea más compartible y navegable (deep linking): Puedes copiar y pegar la URL
Por qué esto es importante
Imagina que encuentras una oferta que te interesa. Si la URL es /jobs/1234, puedes:
- Copiarla y enviarla por WhatsApp
- Guardarla en favoritos
- Recargar la página sin perder contexto
Si la información estuviera solo en el estado de React (sin estar en la URL), al recargar perderías todo.
Múltiples parámetros en la URL
React Router también permite tener más de un parámetro en la ruta.
Por ejemplo, una ruta con id y página:
<Route path="/jobs/:id/page/:page" element={<JobDetail />} />
Y podrías leerlos así:
import { useParams } from 'react-router'
export function JobDetail() {
const { id, page } = useParams()
return (
<>
<h1>Job detail</h1>
<p>La ID es: {id}</p>
<p>Página: {page}</p>
</>
)
}
Ejemplo con URL /jobs/1234/page/2
{
"id": "1234",
"page": "2"
}
Otro ejemplo: keyword en la ruta
En lugar de usar query strings (?keyword=frontend), puedes usar parámetros de ruta:
<Route path="/jobs/keyword/:keyword" element={<JobsSearch />} />
Y en el componente:
export function JobsSearch() {
const { keyword } = useParams()
return (
<>
<h1>Resultados de búsqueda</h1>
<p>Buscando ofertas para: {keyword}</p>
</>
)
}
Esto te permite construir URLs como:
/jobs/keyword/frontend/jobs/keyword/react/jobs/keyword/javascript
¿Cuándo usar parámetros vs query strings?
Usa parámetros de ruta cuando:
- El valor identifica un recurso específico (id de producto, slug de artículo)
- Es esencial para la página (sin él, la página no tiene sentido)
- Quieres URLs más “limpias” y semánticas
Usa query strings cuando:
- Son filtros opcionales (búsqueda, ordenamiento, página)
- La página funciona sin ellos
- Puedes tener muchos parámetros opcionales
Convirtiendo la id en número
Recuerda que useParams() siempre devuelve strings. Si necesitas un número:
export function JobDetail() {
const { id } = useParams()
const numericId = Number(id)
// O usando parseInt
const jobId = parseInt(id, 10)
console.log(typeof id) // "string"
console.log(typeof numericId) // "number"
// ...
}
Esto es útil cuando necesitas hacer comparaciones numéricas o enviar la id a una API que espera números.
Validando parámetros
Es buena práctica validar que el parámetro tenga el formato esperado:
import { useParams, Navigate } from 'react-router'
export function JobDetail() {
const { id } = useParams()
// Si la id no es un número, redirigimos a 404
if (isNaN(Number(id))) {
return <Navigate to="/404" replace />
}
// Resto del componente...
}
O simplemente mostrar un mensaje de error:
export function JobDetail() {
const { id } = useParams()
if (!id || isNaN(Number(id))) {
return (
<div>
<h1>Error</h1>
<p>ID de oferta inválida</p>
</div>
)
}
// Resto del componente...
}
Resumen de la clase
En esta sesión hemos visto:
- Por qué necesitamos rutas dinámicas para mostrar el detalle de una oferta
- Cómo crear una página de detalle
JobDetail - Cómo definir una ruta con parámetros usando
path="/jobs/:id" - Cómo leer los parámetros de la URL con el hook
useParams - Que el nombre del parámetro depende de lo que pongas en el path (
:id,:jobId,:keyword, etc.) - Que podemos tener múltiples parámetros en una misma ruta
- Cómo esa id nos sirve para pedir datos reales a una API
- La diferencia entre parámetros de ruta y query strings
- Cómo validar y convertir parámetros
Con esto ya tienes las bases para trabajar con URLs dinámicas en React Router y construir experiencias mucho más ricas: detalles de productos, perfiles de usuario, páginas de blog con slug, y mucho más.
Las URLs con parámetros hacen que tu aplicación sea más compartible, más navegable y más profesional. Son una pieza fundamental de cualquier aplicación web moderna.