Command Palette

Search for a command to run...

Objeto History: Navegación y Gestión del Historial

Aprende a controlar la navegación del navegador usando history.back(), history.forward(), history.pushState() y más para crear SPAs fluidas.

Lectura: 14 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • El objeto history permite navegar por el historial del navegador programáticamente
  • history.back() y history.forward() simulan los botones atrás y adelante del navegador
  • history.go(n) permite navegar n pasos en el historial
  • history.pushState() agrega una nueva entrada al historial sin recargar la página
  • history.replaceState() modifica la entrada actual del historial sin crear una nueva
  • El evento popstate se dispara cuando el usuario navega por el historial

Introducción al Objeto History

El objeto history es parte del Browser Object Model (BOM) y proporciona una interfaz para manipular el historial de sesiones del navegador. Este historial contiene todas las páginas que el usuario ha visitado durante la sesión actual, permitiendo navegar hacia adelante y atrás como lo harían los botones del navegador.

En las aplicaciones modernas de una sola página (SPAs), el objeto history es fundamental para crear una experiencia de navegación fluida sin recargas completas de página. Métodos como pushState() y replaceState() permiten cambiar la URL y el estado de la aplicación sin que el navegador realice una nueva solicitud HTTP.

  • <strong>Navegación programática:</strong> Controla la navegación sin que el usuario interactúe directamente
  • <strong>SPAs:</strong> Crea aplicaciones de una sola página con navegación fluida
  • <strong>Estado de la aplicación:</strong> Guarda y recupera el estado de la aplicación en cada entrada del historial
  • <strong>URLs limpias:</strong> Usa URLs amigables sin recargar la página
  • <strong>Compatibilidad:</strong> Disponible en todos los navegadores modernos

Historial de Sesión vs Historial Global

El objeto history solo proporciona acceso al historial de la sesión actual del navegador. No puedes acceder al historial completo de navegación del usuario por razones de privacidad. Solo puedes navegar por las páginas visitadas durante la sesión actual.

Método go() para Navegación

El método history.go() es más flexible que back() y forward() porque permite navegar un número específico de pasos en el historial. Acepta un entero como parámetro: un número positivo navega hacia adelante, un número negativo navega hacia atrás, y 0 recarga la página actual.

Parámetros del Método go()

El parámetro del método go() determina cuántas entradas del historial navegar. Por ejemplo, go(-1) es equivalente a back(), go(1) es equivalente a forward(), y go(-2) navega dos páginas atrás.

go-parametros.js
Loading code...

El método go() es especialmente útil cuando necesitas navegar múltiples pasos en el historial. Por ejemplo, en un formulario de varios pasos, puedes usar go(-3) para regresar al inicio del formulario desde el paso final.

Recargar la Página con go(0)

El método history.go(0) recarga la página actual, equivalente a location.reload(). Aunque funciona, es más común usar location.reload() para recargar páginas. Un punto importante: si el valor pasado a go() excede los límites del historial (por ejemplo, go(-100) cuando solo has visitado 5 páginas), el método simplemente no hará nada, sin lanzar error.

go-recargar-pagina.js
Loading code...

Propiedades del Objeto History

El objeto history tiene dos propiedades principales: length y state. La propiedad length indica cuántas entradas hay en el historial de la sesión, mientras que state contiene el objeto de estado asociado con la entrada actual del historial.

Propiedad length

La propiedad history.length devuelve el número de entradas en el historial de la sesión actual. Esto incluye la página actual más todas las páginas que el usuario puede navegar usando back() o forward(). El valor mínimo es 1 (la página actual).

propiedad-length.js
Loading code...

La propiedad length es útil para determinar si el usuario puede navegar atrás o adelante. Por ejemplo, puedes deshabilitar un botón de navegación atrás si length es 1, lo que indica que no hay páginas anteriores en el historial.

Propiedad state

La propiedad history.state devuelve el objeto de estado asociado con la entrada actual del historial. Este estado es el que se pasó como primer parámetro a pushState() o replaceState(). Si no se ha establecido ningún estado, el valor es null.

propiedad-state.js
Loading code...

La propiedad state es fundamental para implementar SPAs. Permite guardar el estado de la aplicación en cada entrada del historial. Importante: siempre usa objetos serializables (JSON) para el estado. Evita pasar funciones, DOM nodes u objetos no serializables, ya que estos no se guardarán correctamente.

  • <strong>Objetos simples:</strong> { page: 'products', filter: 'active' }
  • <strong>Arrays:</strong> ['item1', 'item2', 'item3']
  • <strong>Números y strings:</strong> Valores primitivos serializables
  • <strong>Evitar funciones:</strong> No se pueden serializar a JSON
  • <strong>Evitar DOM nodes:</strong> Referencias a elementos del DOM no funcionan
  • <strong>Tamaño moderado:</strong> Objetos grandes afectan el rendimiento

pushState: Agregar al Historial

El método history.pushState() es uno de los métodos más importantes del objeto history. Permite agregar una nueva entrada al historial de la sesión sin recargar la página. Esto es fundamental para crear SPAs donde la navegación no requiere recargas completas de página.

Sintaxis de pushState()

El método pushState() acepta tres parámetros: un objeto de estado (que se puede recuperar usando history.state), un título (que actualmente es ignorado por la mayoría de los navegadores), y una URL opcional (que puede ser absoluta o relativa).

sintaxis-pushstate.js
Loading code...

Cuando llamas a pushState(), la URL del navegador cambia a la URL especificada, pero la página no se recarga. Esto crea una nueva entrada en el historial, lo que significa que el usuario puede navegar atrás usando el botón atrás del navegador o history.back().

pushState() en SPAs

En aplicaciones de una sola página, pushState() se usa para cambiar la URL cuando el usuario navega a una nueva "página" de la aplicación. Esto permite que cada "página" tenga su propia URL única, lo que mejora la usabilidad y el SEO.

pushstate-spas.js
Loading code...

Este patrón es común en frameworks como React Router y Vue Router. Cuando el usuario navega a una nueva ruta, el framework usa pushState() para cambiar la URL sin recargar la página. Usa pushState() para crear URLs amigables como /products/123 en lugar de hashes como #/products/123, mejorando la legibilidad y el SEO.

replaceState: Reemplazar en el Historial

El método history.replaceState() es similar a pushState(), pero en lugar de agregar una nueva entrada al historial, reemplaza la entrada actual. Esto significa que el usuario no puede navegar atrás a la URL anterior usando el botón atrás del navegador.

Sintaxis de replaceState()

Al igual que pushState(), replaceState() acepta tres parámetros: un objeto de estado, un título (ignorado), y una URL opcional. La diferencia es que replaceState() modifica la entrada actual del historial en lugar de crear una nueva.

sintaxis-replacestate.js
Loading code...

replaceState() es útil cuando quieres cambiar la URL y el estado sin que el usuario pueda navegar atrás. Por ejemplo, después de que un usuario se autentica, puedes reemplazar la URL de login con la URL del dashboard.

Cuándo Usar replaceState()

replaceState() es ideal para situaciones donde no quieres que el usuario pueda navegar atrás a una página anterior. Esto incluye redirecciones, autenticación, y correcciones de URL.

cuando-usar-replacestate.js
Loading code...

Este patrón es común en aplicaciones donde después de una acción importante (como enviar un formulario o completar un proceso), no quieres que el usuario pueda navegar atrás. Sin embargo, ten cuidado: los usuarios esperan poder navegar atrás en la web. Solo usa replaceState() cuando realmente no quieras que el usuario pueda regresar a la página anterior, como después de autenticación o envío de formularios.

Diferencia Clave: pushState vs replaceState

pushState() crea una nueva entrada en el historial (el usuario puede volver atrás). replaceState() modifica la entrada actual (el usuario NO puede volver a la URL anterior). Usa pushState() para navegación normal y replaceState() para redirecciones donde el retorno no tiene sentido.

Evento popstate

El evento popstate se dispara cuando el usuario navega por el historial activo del navegador. Esto incluye cuando el usuario presiona los botones atrás o adelante del navegador, o cuando se llama a history.back(), history.forward(), o history.go().

Escuchar el Evento popstate

Para escuchar el evento popstate, agregas un event listener al objeto window. El evento incluye una propiedad state que contiene el objeto de estado de la entrada del historial a la que se navegó.

escuchar-popstate.js
Loading code...

El evento popstate es fundamental para implementar SPAs. Cuando el usuario navega atrás o adelante, el evento popstate te permite actualizar la interfaz de usuario para reflejar el estado correspondiente a la nueva entrada del historial.

pushState() y replaceState() No Disparan popstate

Es importante entender que pushState() y replaceState() NO disparan el evento popstate. El evento popstate solo se dispara cuando el usuario navega por el historial existente, no cuando se agrega o reemplaza una entrada.

popstate-no-dispara-pushstate.js
Loading code...

Este comportamiento es importante de entender. Si necesitas actualizar la interfaz después de llamar a pushState() o replaceState(), debes hacerlo manualmente. El evento popstate solo se disparará cuando el usuario navegue atrás o adelante usando los botones del navegador o history.back()/forward()/go(). Siempre verifica event.state en el handler de popstate: si es null, significa que el usuario navegó a una página sin estado asociado.

Patrón Común en SPAs

Crea una función navigateTo() que llame a pushState() y actualice la UI. Luego, usa el evento popstate para llamar a la misma función de actualización de UI cuando el usuario navegue con los botones del navegador. Esto mantiene la UI sincronizada con el historial.

Errores Comunes

Al trabajar con el objeto history, hay varios errores comunes que puedes encontrar. Conocer estos errores te ayudará a escribir código más robusto y evitar bugs difíciles de depurar.

URL Inválida en pushState()

Si intentas usar pushState() o replaceState() con una URL inválida, JavaScript lanzará un error. La URL debe ser del mismo origen que la página actual, o ser una URL relativa válida.

error-url-invalida-pushstate.js
Loading code...

Siempre verifica que la URL sea válida antes de llamar a pushState() o replaceState(). Usa try/catch para manejar errores y evitar que la aplicación se rompa.

Estado No Serializable

Si intentas pasar un estado no serializable (como una función o un DOM node) a pushState() o replaceState(), el navegador lanzará un error. El estado debe ser un objeto serializable como JSON. Además, evita guardar objetos muy grandes o complejos: el navegador tiene límites en el tamaño del estado, y objetos grandes afectan el rendimiento de la navegación.

error-estado-no-serializable.js
Loading code...

Siempre usa objetos serializables para el estado. Si necesitas guardar información compleja, conviértela a un formato serializable antes de pasarla a pushState() o replaceState(). Por ejemplo, si tienes una instancia de clase, extrae solo las propiedades necesarias como un objeto plano.

Resumen: Objeto History

Conceptos principales:

  • El objeto history permite navegar por el historial de la sesión del navegador
  • back() y forward() simulan los botones atrás y adelante del navegador
  • go(n) permite navegar n pasos en el historial (positivo adelante, negativo atrás)
  • pushState() agrega una nueva entrada al historial sin recargar la página
  • replaceState() reemplaza la entrada actual del historial sin crear una nueva
  • El evento popstate se dispara cuando el usuario navega por el historial

Mejores prácticas:

  • Usa pushState() para crear SPAs con navegación fluida sin recargas
  • Usa replaceState() para redirecciones donde no quieres que el usuario pueda volver
  • Siempre usa objetos serializables para el estado de history
  • Escucha el evento popstate para actualizar la interfaz cuando el usuario navega
  • Verifica que las URLs sean válidas antes de usar pushState() o replaceState()