-
Notifications
You must be signed in to change notification settings - Fork 961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why is a new location created when navigating to same location? #470
Comments
The |
From the WHATWG browser spec
Where "equals" is defined here (basically, |
I haven't done an exhaustive search, but the only place that I have seen a different behavior has been on GitHub repo pages. If you go to https://github.com/ReactTraining/history and click the They call I would say that 1) This is different than how this package behaves because they are manually calling While my initial thought would be to modify history.navigate(to);
navigate = (location) {
if (isSameLocation(location, history.location) {
replace(location)
} else {
push(location)
}
} |
As @vladshcherbin noted here remix-run/react-router#5363 (comment), earlier versions of I'm not sure if the new API that I proposed in #472 is the approach that you want to take here @mjackson, but that behavior should definitely be brought back in some form. |
Came here because I also discovered that duplicates were being created in history. I tend to agree with the API that @pshrmn suggested. Seems to give us the best of both worlds - fall into line with how developers seem to assume history works when the same location is |
Just discovered this issue as well. Any updates? Seems to me this isn't the sort of issue that should be left unresolved. It may seem like an "edge case", but I could easily imagine a frustrated user spam-clicking a nav link (maybe because they are waiting for ajax content to load and they think it is stuck). Then their back button "stops working" and they have no idea why. @pshrmn 's suggestion seems solid. |
Let's just fix |
I think that it is a matter of intent. If The benefit of having a method explicitly designed to mimic anchor behavior is that |
@pshrmn users are forced to have a broken It would be great to have |
At the end of the day, I'm not super invested one way or the other. I think that a new function would be more correct (I would argue that |
Previously, it did not open in a new tab. Now it does. However, this introduces a regression that was fixed in 97a54bd Now if a user clicks on 'Create Tournament' when at /create-tournament, and then tries to press back, the user will still be at /create-tournament until the user presses back again. Personally I feel as if browsing back through the history is less of an issue compared to non-standard ctrl-click behaviour. The issue with react-router Link pushing the same path multiple times can be tracked in: remix-run/react-router#5039 remix-run/history#470
Something just occurred to me: maybe clicking on links is different than calling So, the current behavior is to create a new location in However, there may be some special behavior in browsers that checks the behavior of a click on a link and decides "hey, this person is already at that URL. do nothing". |
Yes, a link click isn't always a I wish there was a History API method for this middle ground since everyone has to roll their own "is it push or replace" functionality. |
What I'm saying is that |
Yeah, that's the behavior that the above quote from the WHATWG spec describes. That could either be done in React Router's My comment about the History API was just that I wish there was a |
A reason why you would want that method in |
OK, sure. We can have a I believe you've suggested using
|
I like As far as implementation goes, I had written one in #472. I'm not sure if you want to go with something like that (I had moved the push/replace code out of the |
It is a critical issue. Right now there is no way to prevent accumulate same url into history stack. It makes no sense... I'm going to use this closed (I do not know why) pull request #558 |
Finally I found a solution. Basically monkey patching.... props.history.listen(location => {
lastLocation = location
})
// monkey patching to prevent pushing same url into history stack
const prevHistoryPush = props.history.push
props.history.push = (pathname, state = {}) => {
if (lastLocation === null ||
pathname !== lastLocation.pathname + lastLocation.search + lastLocation.hash ||
JSON.stringify(state) !== JSON.stringify(lastLocation.state)
) {
prevHistoryPush(pathname, state)
}
} |
@dabit1 @vladshcherbin The problem with the proposed fix is that the There is a new path though; Create a new method that does the same as your monkeypatch, but under a new name. Then let the ReactHistory We're getting closer, the problem just needs an owner. (I might pick this up when I have the time.) |
Hi @guidobouman @vladshcherbin, finally I created that pull request: 👍 |
workaround for the error: https://filipmolcik.com/react-router-warning-hash-history-cannot-push-the-same-path/ edit: slightly less fucked version: https://gist.github.com/chpio/a5d4f7d73d6643780db20db163561a67 |
Where should I put the code? |
@sky93 in the main route. Check it out: import React, { Component } from 'react'
import {
BrowserRouter,
Route
} from 'react-router-dom'
import ModalCheck from './modal-check'
class MainRouter extends Component {
render () {
let lastLocation = null
return (
<BrowserRouter>
<Route component={props => {
props.history.listen(location => {
lastLocation = location
})
// monkey patching to prevent pushing same url into history stack
const prevHistoryPush = props.history.push
props.history.push = (pathname, state = {}) => {
if (lastLocation === null ||
pathname !== lastLocation.pathname + lastLocation.search + lastLocation.hash ||
JSON.stringify(state) !== JSON.stringify(lastLocation.state)
) {
prevHistoryPush(pathname, state)
}
}
return <ModalCheck {...props} store={this.props.store} />
}} />
</BrowserRouter>
)
}
}
export default MainRouter |
I just had the same issue, and tried your workaround... but also found a few issues with it, so I tweaked it a little bit:
Basically - I am using Router instead of BrowserRouter, and passing it a customHistory prop - docs |
I believe the right place to fix this is in react-router. Instead of introducing extra methods (and semantics) in history, we should just replace instead of push when the location pathname + search are the same and a link is clicked. history doesn't even have the concept of a link click, so this isn't the right place for it. We'll follow up in remix-run/react-router#5362 |
I get that you want to keep the API as close to the browser native history API as possible. But this way, all apps that want to programatically navigate like a link will have to rebuild this diffing logic all the time: #470 (comment) Or do you plan to introduce a higher-level API in react-router? |
This was brought up in remix-run/react-router#5039, but is more appropriate here.
Basically, the problem is that if you are on page
/here
and click a link to/here
, you end up with essentially duplicate (just differentkey
s) location objects. Then, clicking the back button will bring you back to/here
. This is obviously intentional because thePushSamePath
test sequence exists, but I'm not completely sure why.However, that seems to differ from how browsers handle clicking on links to the same location. They seem to essentially do a
replaceState
when clicking a link that points to the same location (if you are on/here
, click a link to/other
, click the back button so that you are back on/here
and click a link to/here
, it does not wipe out the future location). Callingwindow.location.href
with the same path also does not wipe out future locations, so I think that behavior is different for users who use theforceRefresh
option.I'm not sure what the ideal solution would be. I feel like it should be
history
that accommodates this.For example, if it was left to other packages to adapt to this,
react-router-dom
's<Link>
would have to be able to detect when itsto
is the same as the current location and callhistory.replace
instead ofhistory.push
.My initial instinct would be that
push
should detect when it is pushing the same location and callreplaceState
instead ofpushState
.The text was updated successfully, but these errors were encountered: