Skip to content

fix(liveview): don't double the ? and # when reading the browser location - #5836

Merged
nicoburns merged 1 commit into
DioxusLabs:mainfrom
Dev-next-gen:fix/liveview-location-query-hash
Sep 16, 2026
Merged

nicoburns merged 1 commit into
DioxusLabs:mainfrom
Dev-next-gen:fix/liveview-location-query-hash

Conversation

@Dev-next-gen

Copy link
Copy Markdown
Contributor

I was reading packages/liveview/src/history.rs next to the web history and noticed the two read the browser location differently. The web history builds the route as pathname + search + hash, while LiveviewHistory does pathname + "?" + search + "#" + hash. location.search and location.hash already include their leading ? and #, so for http://localhost/search?query=hello&word_count=8#top LiveviewHistory produces /search??query=hello&word_count=8##top. That happens both in the initial eval and in the popstate listener.

The router's from_str splits on the first # and ?, so the query it sees is ?query=hello&word_count=8: the first key becomes ?query, which matches nothing, and the parameter is silently dropped. A plain path without a query ends up as /path?#, which is why this doesn't show up in the basic case.

To check it, I wrote a throwaway test in packages/router/tests (not part of this PR) that pulls the exact JS expression out of history.rs, runs it with node against a mocked document.location, and parses the result with a #[route("/search?:query&:word_count")] enum:

Before:

liveview route string: "/search??query=hello&word_count=8##top"
  left: Search { query: "", word_count: 8 }
 right: Search { query: "hello", word_count: 8 }
test result: FAILED

After:

test liveview_location_keeps_query ... ok

cargo check -p dioxus-liveview passes. The change only touches the JS string inside the crate-private LiveviewHistory, and the separators aren't lost since they come from search and hash themselves, so the route string now matches what the web renderer already gives the router. From reading the code, the same string is also passed back to history.replaceState, so the doubled ??/## would end up in the address bar too, but I only verified the parsing side, not a running liveview app.

AI tools used

…location

`location.search` and `location.hash` already start with `?` and `#`, so
LiveviewHistory built routes like `/search??query=hello#` and `##top`. The
router then saw a query key of `?query`, which silently dropped the first
query parameter on page load and after back/forward navigation.

Build the route the same way the web history does: pathname + search + hash.
@nicoburns
nicoburns merged commit fda3dc9 into DioxusLabs:main Sep 16, 2026
18 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants