Skip to content

createBrowserHistory discards existing History and Navigation API entry state during initialization #8735

Open

Description

@callie-openai

Which project does this relate to?

Router

Describe the bug

createBrowserHistory() adds its initial key by calling history.replaceState with a new object. When the entry has neither key nor __TSR_key, this drops existing application fields, resets an existing __TSR_index, and clears the independent Navigation API entry state. No navigation is necessary to trigger it.

Verified with unmodified @tanstack/history@1.162.4 in Chromium 151.0.7922.34. The same reproduction fails with public source commit 18154b1c45454a70aa77e9d6d27c8a6e0733d031.

All three synthetic cases (null, false, and an object Navigation API state) report preserved: false. After initialization, History state contains only the generated keys and __TSR_index: 0. Navigation entry state is undefined.

Complete minimal reproducer

https://gist.github.com/callie-openai/5ea3f094b7d1d981f753bf4868ba27ec

Steps to Reproduce the Bug

  1. Clone the public reproduction:
git clone https://gist.github.com/5ea3f094b7d1d981f753bf4868ba27ec.git history-initialization-repro
cd history-initialization-repro
npm install
npm start
  1. Open http://127.0.0.1:8000 in a browser supporting the Navigation API.
  2. Observe all three cases print preserved: false.

The two-file example uses only the pinned public History package and Node's built-in HTTP server. Each case sets { color: "blue", __TSR_index: 7 }, sets independent Navigation API state, constructs browser History, and reads both states immediately afterward.

Expected behavior

Initialization should add the router's keys while preserving the existing color field, index 7, and independent Navigation API entry state, including null and false. All three cases should print preserved: true.

Screenshots or Videos

No response

Platform

  • Package: @tanstack/history 1.162.4
  • Also reproduced from Router source commit 18154b1
  • OS: macOS
  • Browser: Chromium 151.0.7922.34
  • Runtime for local HTTP server: Node.js 24.22.0
  • Bundler: none

Additional context

The initialization branch in packages/history/src/index.ts should retain the existing History state and use its existing index when present. Native replaceState also clears Navigation API state, so snapshot that independent state before the call and restore it with navigation.updateCurrentEntry when it is not undefined. A truthiness check would incorrectly drop null and false.

Applying those changes to the 1.162.4 source makes all three browser cases report preserved: true. Already-keyed entries need no extra initialization mutation.

This is distinct from #3907 / #8724, which address missing indexes on entries that already have a router key.

Source inspected: https://github.com/TanStack/router/blob/18154b1c45454a70aa77e9d6d27c8a6e0733d031/packages/history/src/index.ts

Activity

  1. AmineBenzaazaa commented on Oct 17, 2026

    @AmineBenzaazaa

    I'll open a PR for this: keep the existing state fields and __TSR_index when adding the initial key, and restore the Navigation API entry state after replaceState when it isn't undefined, with unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions