Skip to content
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

Prevent pushing duplicate paths to the history API. #558

Closed
wants to merge 9 commits into from

Conversation

guidobouman
Copy link
Contributor

@guidobouman guidobouman commented Jan 11, 2018

Fixes #507

@guidobouman
Copy link
Contributor Author

Okay, this is a little bigger...

HashHistory emits a warning about replacing instead of pushing to the stack. But this is actually the WHATWG standards behaviour. So should I remove the warning from the HashHistory and homogenise the implementation around BrowserHistory, MemoryHistory & HashHistory?

@@ -165,6 +165,11 @@ const createBrowserHistory = (props = {}) => {
const action = "PUSH"
const location = createLocation(path, state, createKey(), history.location)

if (createPath(location) === createPath(history.location)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're only comparing the pathname in this case. What about the search/querystring? Since you're doing this in multiple histories, you should export a common function, like locationsAreEqual.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great tip, thanks.

There's already a locationsAreEqual method, which is great. But it also checks for key, something we don't want. Should I add an override to the method?

That would result in the following signature:

locationsAreEqual = (a, b, ignoreKey) => { ... }

Sounds reasonable if you ask me. On the other hand, invoking the function gets a bit vague that way:

locationsAreEqual(location, oldLocation, true)

I could also create a new method locationsExceptKeyAreEqual or locationEqualsDestination. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure why key is in there at all. If the key is equal, the locations are equal. That's the point of the key value being in there. So, that function would appear to be fundamentally flawed. There's only one internal usage:

https://github.com/ReactTraining/history/blob/dca21eaa9230ae187c72ef657f70aac97cb172aa/modules/createHashHistory.js#L110

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see why. Hash histories don't use key. I haven't been following those specifics too carefully, since I don't use those myself.

I would add a locationsAreEquivalent function in this case that checks pathname and search are equal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for thinking along!

Looks like the key prop could be removed from the compare function, right? As hash history doesn't use the key prop anyhow. Then it would be usable in all places without adding an extra method.

@guidobouman
Copy link
Contributor Author

Rewrote history a little. Not too smart for open-source, oops.

@guidobouman
Copy link
Contributor Author

I see that semi-colons have been enabled in Prettier, I'll fix the conflicts.

@guidobouman
Copy link
Contributor Author

Waiting for #559 before I can fix the conflicts in this branch.

@guidobouman
Copy link
Contributor Author

@timdorr Ready for review again!

PS: What about the HashHistory warning?

@loganpowell
Copy link

subscribing to this as mentioned in #507 (comment)

@mjackson
Copy link
Member

HashHistory emits a warning about replacing instead of pushing to the stack. But this is actually the WHATWG standards behaviour.

What do you mean @guidobouman? It's not possible to push the same path using hash history the way it is currently implemented.

screen shot 2018-01-18 at 9 08 19 pm

Notice how the second window.location.hash = '/home' does not increase window.history.length. This means that pushing the same path using hash history does not create a new entry in the browser's history stack.

@mjackson
Copy link
Member

I should also note that using pushState does push a new entry onto the history stack, even if the paths are the same.

screen shot 2018-01-18 at 9 12 25 pm

If I understand you correctly, @guidobouman, are you saying it shouldn't?

@timdorr
Copy link
Member

timdorr commented Jan 19, 2018

Perhaps we should fix this higher up in React Router's <Link> component? It's ultimately to fix a behavior to match <a> more closely.

@guidobouman
Copy link
Contributor Author

Moving the discussion on this to #470, there's more historical info there.

@mjackson
Copy link
Member

Based on the discussion in #470 I don't think we want to change the behavior of push since pushState does in fact push a new URL onto the history stack. Instead, the proposal is to add a new history.link API that behaves more like clicking on a link would do.

I'm going to close this PR, but thank you for taking the time to push this discussion forward @guidobouman :)

@mjackson mjackson closed this Jan 21, 2018
@guidobouman
Copy link
Contributor Author

guidobouman commented Jan 21, 2018

Always, @mjackson!

PS: I added some small bug fixes / tweaks in this PR, I'll put them up as different PR's.

@guidobouman guidobouman deleted the patch-1 branch January 21, 2018 21:06
@lock lock bot locked as resolved and limited conversation to collaborators Jun 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants