▶ 1. Instalación y Setup
Terminal
# Instalar en tu proyecto Vite
npm install react-router-dom
main.jsx — envolver la app
import { BrowserRouter } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root'))
  .render(
    <BrowserRouter>
      <App />
    </BrowserRouter>
  )
<BrowserRouter> clave
Proveedor raíz. Usa la History API del navegador. Solo debe haber uno por app. Va en main.jsx.
▶ 2. <Routes> y <Route>
App.jsx — configurar rutas
import { Routes, Route } from 'react-router-dom'

function App() {
  return (
    <>
      <Navbar />         // fuera → siempre visible
      <Routes>
        <Route path="/"         element={<Home />} />
        <Route path="/about"    element={<About />} />
        <Route path="/post/:id" element={<Post />} />
        <Route path="*"         element={<NotFound />} />
      </Routes>
      <Footer />         // fuera → siempre visible
    </>
  )
}
<Routes>
Renderiza solo el primer <Route> que coincide con la URL actual.
path="*"clave
Comodín (wildcard). Captura cualquier URL que no coincidió antes. Siempre va al final.
▶ 3. <Link> y <NavLink>
<a href> evitar
Recarga la página completa y destruye todo el estado de React. Nunca lo uses para navegar dentro de la app.
<Link to> clave
Navega sin recargar. Preserva el estado. Genera un <a> en el HTML final pero intercepta el clic.
Ejemplos
import { Link, NavLink } from 'react-router-dom'

// Link básico
<Link to="/perfil">Mi Perfil</Link>

// Link dinámico con template literal
<Link to={`/post/${articulo.id}`}>Leer más</Link>

// NavLink: agrega clase "active" automáticamente
<NavLink
  to="/inicio"
  className={({ isActive }) =>
    isActive ? "text-violet-400 font-bold" : "text-white"
  }
>Inicio</NavLink>
<NavLink>
Igual que <Link> pero recibe una función en className con { isActive }. Perfecto para resaltar el ítem activo del menú.
▶ 4. useParams
useParams() clave
Lee los segmentos dinámicos de la URL (los que empiezan con : en el path). Siempre devuelve strings.
Ruta configurada en App.jsx
<Route path="/post/:id" element={<PostDetail />} />
PostDetail.jsx — leer el parámetro
import { useParams } from 'react-router-dom'

function PostDetail() {
  const { id } = useParams()
  // URL /post/42  →  id === "42" (string)
  // Convertir a número si hace falta:
  const numId = Number(id)

  return <h1>Post #{id}</h1>
}
Number(id)ojo
useParams siempre devuelve strings. Si necesitás comparar con IDs numéricos, convertí con Number(id).
▶ 5. useNavigate
useNavigate() clave
Navega de forma programática (desde código, no desde un clic en un Link). Útil después de un login, submit de formulario, etc.
Ejemplo — redirigir después de login
import { useNavigate } from 'react-router-dom'

function LoginForm() {
  const navigate = useNavigate()

  function handleSubmit(e) {
    e.preventDefault()
    // ... lógica de login ...
    navigate('/dashboard')  // ir hacia adelante
  }

  return <form onSubmit={handleSubmit}>...</form>
}
navigate(-1)
Equivale al botón "Atrás" del navegador. Podés usar cualquier número: navigate(-2) retrocede 2 páginas.
replace: true
navigate('/ruta', { replace: true }) reemplaza la entrada actual en el historial, en vez de agregar una nueva.
▶ 6. useLocation
useLocation()
Devuelve el objeto de la ubicación actual. Útil para saber en qué ruta estás, leer query strings o pasar estado entre rutas.
Propiedades del objeto location
import { useLocation } from 'react-router-dom'

function MiComponente() {
  const location = useLocation()

  location.pathname  // "/post/42"
  location.search    // "?page=2&sort=date"
  location.hash      // "#seccion-1"
  location.state     // estado pasado con navigate()
}
Leer query params (?page=2)
const location = useLocation()
const params = new URLSearchParams(location.search)
const page = params.get('page')  // "2"
▶ 7. Patrones de Rutas
/rutaestática
Coincide exactamente con esa URL. Ej: /about, /contacto.
/ruta/:paramdinámica
El :param captura cualquier segmento. Ej: /post/:id coincide con /post/1, /post/hola, etc.
/:a/:b
Múltiples parámetros. Ej: /cat/:categoria/post/:id. Se leen todos con useParams().
path="*"al final
Comodín: captura todo lo que no coincidió. Siempre debe ir como última <Route>.
Ejemplo con múltiples params
// Route:
<Route path="/tienda/:categoria/:id" element={<Producto />} />

// URL: /tienda/ropa/42
const { categoria, id } = useParams()
// categoria === "ropa"  |  id === "42"
▶ 8. Rutas Anidadas + <Outlet>
<Outlet /> avanzado
Marca el lugar donde se renderiza el componente hijo de una ruta anidada. El componente padre actúa como un "layout".
Configuración en App.jsx
<Routes>
  <Route path="/dashboard" element={<DashboardLayout />}>
    // Estas rutas se renderizan DENTRO de DashboardLayout
    <Route index             element={<DashHome />} />
    <Route path="perfil"   element={<DashPerfil />} />
    <Route path="config"   element={<DashConfig />} />
  </Route>
</Routes>
DashboardLayout.jsx — usa <Outlet />
import { Outlet, Link } from 'react-router-dom'

function DashboardLayout() {
  return (
    <div className="flex">
      <aside>
        <Link to="perfil">Perfil</Link>
        <Link to="config">Config</Link>
      </aside>
      <main>
        <Outlet />  // aquí se renderiza la ruta hija
      </main>
    </div>
  )
}
index
La ruta index es la ruta "por defecto" del padre. Se activa cuando la URL coincide exactamente con la del padre (/dashboard).
▶ 9. Resumen de Hooks
useParams()clave
Lee los parámetros dinámicos de la URL (:id, :slug…). Devuelve un objeto con strings.
useNavigate()clave
Navega por código. navigate('/ruta'), navigate(-1) (atrás), navigate(1) (adelante).
useLocation()
Objeto con la URL actual: .pathname, .search, .hash, .state.
useSearchParams()
Lee y escribe los query params (?clave=valor). Similar a useState pero sincronizado con la URL.
useSearchParams — ejemplo
import { useSearchParams } from 'react-router-dom'

const [searchParams, setSearchParams] = useSearchParams()

// Leer: URL → /posts?page=3
const page = searchParams.get('page')  // "3"

// Escribir: cambia la URL a /posts?page=4
setSearchParams({ page: '4' })