react-router: Link to={locationObject} has inconsistent behavior between search and hash.

Version

5.0.0

Test Case

https://codesandbox.io/s/wyxq313458

Expected Behavior

Based on the comments on #6713, I expect that <Link to={{ hash: "hash"}}/> and <Link to ={{ search: "search"}}/> behave the same, in that they link to the basename of the router. Or that both link to the current location + hash / search.

Especially noteworthy is the difference between { search: "search"} - which just appends the search - and { hash: "hash", search: "search"} which links to basename + hash + search.

I’d also expect that after navigating with such a Link, that the URL I see in the browser is reflected in the routing. But that isn’t the case.

Actual Behavior

Part 1: Link targets

Given the basename “root” and the current location “path”:

“to” prop target url
{hash: "hash"} /root#hash
"#hash" /root/path#hash
{search: "search"} /root/path?search
"?search" /root/path?search
{search: "search", hash: "hash"} /root#hash?search

Consistent would be:

“to” prop target url
{hash: "hash"} /root#hash
"#hash" /root/path#hash
{search: "search"} /root?search
"?search" /root/path?search
"#hash?search" /root/path#hash?search
{search: "search", hash: "hash"} /root#hash?search

Part 2: Routing

When clicking on a Link without a pathname specified, the user is navigated to the baseName / root URL. But the Router still matches the prior path. You can test that in the above sandbox by clicking on the “otherpath”, then clicking on the “HASH location object” link. It still matches and renders the OtherPath route.

Screenshot_2019-04-23 CodeSandbox

Part 3: BrowserRouter vs. HashRouter

Edit: I just had the idea to check if the behavior is the same for different Routers. It’s not. MemoryRouter and BrowserRouter seem to behave the same, but HashRouter is different for { search: "search"}. Both in terms of target URLs (see below) and in that the location object sans pathname causes the expected route change based on the new URL.

“to” prop target url - browserRouter target url hashRouter
{hash: "hash"} /root#hash #/root#hash
"#hash" /root/path#hash #/root/path#hash
{search: "search"} /root/path?search #/root?search
"?search" /root/path?search #/root/path?search
"#hash?search" /root/path#hash?search #/root/path#hash?search
{search: "search", hash: "hash"} /root#hash?search #/root/path#hash?search

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (16 by maintainers)

Most upvoted comments

I appeneded differences between HashRouter and BrowserRouter.

I will take a closer look at it later. I think the source of both problems is the same and the solution for one will fix the other problem.