Start · Sprachen · JavaScript · Referenz · History.replaceState()

History.replaceState()

Methode

Ersetzt den aktuellen Eintrag der Browser-Historie durch ein neues Zustandsobjekt und optional eine neue URL, ohne die Seite neu zu laden.

seit JavaScript Baseline: alle Browser (HTML5) Kategorie: webapi

Signatur

History.prototype.replaceState(state, unused, url)

Beschreibung

history.replaceState() verändert den aktuellen Eintrag im Sitzungsverlauf. Anders als history.pushState() legt die Methode keinen neuen Eintrag an. Die Länge von history.length bleibt also gleich, und der Zurück-Button führt weiterhin zur vorherigen Seite.

Typische Einsatzfälle:

  • Filter-, Such- oder Sortierparameter in der URL aktuell halten, ohne den Verlauf mit vielen Einträgen zu füllen.
  • Einen Anfangszustand für den ersten Eintrag einer Single-Page-App festlegen. Dieser wird später bei popstate gebraucht.
  • URLs aufräumen, etwa Tracking- oder Einmal-Parameter wie ?token=… nach dem Login entfernen.
  • Die Scrollposition oder den UI-Zustand im aktuellen Eintrag speichern, damit er bei der Rückkehr wiederhergestellt werden kann.

Der Aufruf löst kein popstate-Ereignis aus und lädt die Seite nicht neu. Der Browser prüft auch nicht, ob die neue URL auf dem Server existiert. Das gespeicherte Zustandsobjekt kann man danach über history.state lesen.

Parameter

Name Typ Default Beschreibung
$state Pflicht any Beliebiger Wert, der mit dem strukturierten Klon-Algorithmus serialisiert werden kann, z. B. ein Objekt, ein Array oder null. Er ist danach über history.state und event.state bei popstate erreichbar. Funktionen und DOM-Knoten sind nicht erlaubt.
$unused Pflicht string Wird aus historischen Gründen noch verlangt (früher title) und von Browsern ignoriert. Üblich ist eine leere Zeichenkette ''.
$url string | URL aktuelle URL Neue URL für den aktuellen Eintrag, absolut oder relativ. Sie muss denselben Ursprung (Schema, Host, Port) wie das Dokument haben. Ohne Angabe bleibt die URL unverändert.

Rückgabewert

Typ
void
Beschreibung
Gibt undefined zurück.

Beispiele

Filterparameter in der URL aktualisieren, ohne neuen Verlaufseintrag

const updateFilter = (key, value) => {
  const url = new URL(location.href);
  if (value) {
    url.searchParams.set(key, value);
  } else {
    url.searchParams.delete(key);
  }
  history.replaceState(history.state, '', url);
};

// z. B. bei jeder Eingabe im Suchfeld
document.querySelector('#suche').addEventListener('input', (e) => {
  updateFilter('q', e.target.value.trim());
});
URL wird z. B. zu /produkte?q=schuhe, history.length bleibt unverändert

Anfangszustand für eine Single-Page-App setzen

// Beim Start: aktuellen Eintrag mit Zustand versehen
history.replaceState({ view: 'home' }, '', location.pathname);

const navigate = (view) => {
  history.pushState({ view }, '', `/${view}`);
  render(view);
};

window.addEventListener('popstate', (event) => {
  // Auch beim Zurückkehren zum ersten Eintrag ist event.state gesetzt
  render(event.state?.view ?? 'home');
});

function render(view) {
  console.log('Zeige Ansicht:', view);
}

console.log(history.state);
{ view: 'home' }

Einmal-Token nach dem Login aus der URL entfernen

// Aufruf z. B. über /dashboard?token=abc123&tab=stats
const url = new URL(location.href);
const token = url.searchParams.get('token');

if (token) {
  sessionStorage.setItem('authToken', token);
  url.searchParams.delete('token');
  history.replaceState(null, '', url.pathname + url.search + url.hash);
}

console.log(location.href);
https://example.com/dashboard?tab=stats

Scrollposition im aktuellen Eintrag merken

let timer;
window.addEventListener('scroll', () => {
  clearTimeout(timer);
  // Entprellen: nicht bei jedem Scroll-Ereignis schreiben
  timer = setTimeout(() => {
    history.replaceState({ ...history.state, scrollY: window.scrollY }, '');
  }, 200);
});

window.addEventListener('popstate', (e) => {
  if (e.state?.scrollY != null) window.scrollTo(0, e.state.scrollY);
});

// Wichtig · Fallstricke

  • Gleicher Ursprung: Eine URL mit anderem Ursprung löst eine SecurityError-DOMException aus. Das gilt auch für den Wechsel von http zu https oder eine andere Subdomain.
  • Kein popstate: replaceState() löst selbst kein popstate-Ereignis aus. Die Oberfläche muss man also selbst neu zeichnen.
  • Klonbarkeit: Nicht klonbare Werte wie Funktionen, DOM-Knoten oder Klasseninstanzen mit Methoden werfen eine DataCloneError. Klasseninstanzen verlieren beim Klonen außerdem ihren Prototyp. Browser begrenzen die Größe des Zustands, Firefox z. B. auf etwa 16 MiB. Große Daten gehören besser in sessionStorage oder IndexedDB.
  • Drosselung: Browser begrenzen häufige Aufrufe. Safari und Chrome werfen ab etwa 100 Aufrufen in kurzer Zeit eine SecurityError oder ignorieren die Aufrufe. Bei Scroll- oder Eingabe-Ereignissen deshalb entprellen.
  • Serverseitiges Routing: Die neue URL wird nicht beim Server abgefragt. Wird die Seite neu geladen, muss der Server diese URL aber beantworten können, z. B. über einen Fallback auf index.html.
  • Zweiter Parameter: Das frühere title-Argument wird ignoriert. Den Seitentitel ändert man über document.title.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. In file://-Kontexten und manchen Sandbox-iframes können Einschränkungen gelten. Die neuere Navigation API (navigation.navigate(url, { history: 'replace' })) ist eine Alternative, die aber noch nicht überall verfügbar ist.