history.pushState()

Ajoute une nouvelle entrée à l’historique du navigateur et change l’adresse dans la barre sans recharger la page.

Renvoie
undefined
Sur cette page

Exemple

#
JavaScript
function showLesson(number) {
  document.querySelector('#title').textContent = `Leçon ${number}`
}

function goToLesson(number) {
  showLesson(number)
  history.pushState({ lesson: number }, '', `/cours/javascript/lecon-${number}`)
}

goToLesson(6)

console.log(location.pathname)
console.log(history.state)
Résultat
/cours/javascript/lecon-6
{ lesson: 6 }

Dans le cadre isolé de l’aperçu, changer l’adresse est bloqué (SecurityError), donc cet exemple ne s’exécute pas ici. Sur une page normale, l’adresse dans la barre devient /cours/javascript/lecon-6, et la page ne se recharge pas.

Définition et utilisation

#

La méthode history.pushState() change l’adresse visible dans la barre du navigateur et ajoute une nouvelle entrée à l’historique de l’onglet, mais ne recharge pas la page et ne récupère rien du serveur. C’est sur cela que reposent les applications une page (SPA) : vous changez le contenu avec JavaScript, et l’adresse suit ce que voit l’utilisateur, donc elle peut être copiée, ajoutée aux favoris ou actualisée.

Le premier argument est la donnée (l’état) associée à l’entrée, par exemple { lesson: 5 }. Elle doit pouvoir être clonée, comme avec structuredClone(), donc les fonctions et les éléments du DOM sont exclus. Le deuxième argument, les navigateurs l’ignorent, mais il faut quand même le fournir, en général comme une chaîne vide. Le troisième est la nouvelle adresse : elle peut être relative, mais doit appartenir à la même origine (origin), sinon la méthode lève une erreur.

Quand l’utilisateur clique sur « Précédent » ou « Suivant », le navigateur déclenche sur window l’événement popstate et transmet dans event.state la donnée enregistrée avec l’entrée. C’est à vous de montrer alors le contenu correspondant. pushState() seul ne déclenche pas l’événement popstate.

La méthode sœur history.replaceState() prend les mêmes arguments, mais remplace l’entrée actuelle au lieu d’en ajouter une nouvelle. Elle est utile par exemple pour un changement de filtres qui ne devrait pas remplir l’historique. Gardez à l’esprit qu’après une actualisation de la page, le navigateur demande la nouvelle adresse au serveur, qui doit donc savoir la gérer.

Syntaxe

#
Syntaxe
history.pushState(state, unused)
history.pushState(state, unused, url)

history.replaceState(state, unused, url)
history.state
window.addEventListener("popstate", listener)

Paramètres

#
  • state

    valeur quelconque, clonable

    La donnée enregistrée avec l’entrée d’historique. Elle revient dans event.state de l’événement popstate et dans history.state.
  • unused

    chaîne

    Un paramètre conservé pour des raisons historiques. Fournissez une chaîne vide "".
  • url

    chaîne ou URL, optionnel

    La nouvelle adresse, relative ou absolue, de la même origine que la page. Sans elle, l’adresse ne change pas.

Plus d’exemples

#
Gérer le bouton Précédent avec popstate
JavaScript
const title = document.querySelector('#title')

function render(lesson) {
  title.textContent = `Leçon ${lesson}`
  console.log(`J’affiche la leçon ${lesson}`)
}

window.addEventListener('popstate', (event) => {
  render(event.state?.lesson ?? 1)
})

history.pushState({ lesson: 6 }, '', '/cours/javascript/lecon-6')
render(6)
history.pushState({ lesson: 7 }, '', '/cours/javascript/lecon-7')
render(7)

history.back()
Résultat
J’affiche la leçon 6
J’affiche la leçon 7
J’affiche la leçon 6

history.back() agit comme un clic sur « Précédent » : le navigateur revient à l’entrée précédente et déclenche l’événement popstate avec l’état enregistré { lesson: 6 }. La page ne se recharge pas, et c’est la fonction render() qui restitue le contenu.

replaceState() lors d’un changement de filtres
JavaScript
function applyFilter(level) {
  const url = new URL(location.href)
  url.searchParams.set('niveau', level)
  history.replaceState(null, '', url)
  console.log(location.search)
}

applyFilter('débutant')
applyFilter('intermédiaire')
Résultat
?niveau=d%C3%A9butant
?niveau=interm%C3%A9diaire

Chaque appel remplace l’entrée actuelle de l’historique, donc « Précédent » ne repasse pas par les filtres précédents : il revient directement à la page antérieure. Le résultat suppose une page qui n’avait au départ aucun paramètre dans l’adresse.

Compatibilité des navigateurs

#

Largement disponible

Fonctionne dans tous les navigateurs modernes, y compris sur mobile. Vous pouvez l’utiliser sans crainte.

  • Chrome
  • Edge
  • Firefox
  • Safari

Bonnes pratiques

#
  • Après pushState(), gérez toujours l’événement popstate. Sans cela, le bouton « Précédent » change l’adresse, mais le contenu de la page reste l’ancien.
  • N’enregistrez dans l’état que des données simples, par exemple l’identifiant d’une leçon. Les fonctions et les éléments du DOM ne se clonent pas et provoqueront une erreur DataCloneError.
  • Assurez-vous que le serveur gère les adresses créées par pushState(). Après une actualisation de la page ou un accès depuis un favori, le navigateur les demandera au serveur.

Entrées associées

#

Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.