Skip to content
This repository has been archived by the owner on Oct 26, 2018. It is now read-only.

Handle routing state and replace #38

Merged
merged 6 commits into from
Nov 27, 2015

Conversation

kimjoar
Copy link
Collaborator

@kimjoar kimjoar commented Nov 19, 2015

A couple of different changes here. Could split into multiple PRs, but wanted to see if you're interested first (I've also of course seen the PRs that already exist, but just copied this from the changes I needed for my app)

The changes:

  • No longer use window.location, always rely on the location we receive from history
  • Because of the above, let the initial state not be the current url, but set is with noRouterUpdate=true
  • Add handling of location.state (and therefore a deep equal check when comparing locations)
  • Use history.createPath instead of locationToString
  • Make it possible to replace in addition to push

Also thought about renaming, but didn't for this PR:

  • updatePath to pushPath (closer to history.push and history.replace)
  • noRouterUpdate to skipUpdate or noUpdate
  • syncReduxAndRouter to syncReduxAndHistory

@MattKunze MattKunze mentioned this pull request Nov 23, 2015
@jlongster
Copy link
Member

This is looking good. I really don't want to do a deep comparison on state though; luckily, I figured out they comparing locations is the wrong way to detect changes anyway. See the new sync logic at #40. I'm going to merge it after I write some basic tests.

I need this to be rebased on top of that once I land that. Thanks a lot for this PR! Either go ahead and rebase or I'll ping you when it's merged.

@jlongster
Copy link
Member

Also see #21 (comment). I'm not sure if we want to change actions names or not.

@MattKunze
Copy link

Since this is already changing the API for updatePath, any thoughts on losing the ordinal boolean parameters? updatePath( path, null, true ) doesn't read as well as updatePath( path, null, { noRouterUpdate: true } )

Or for that matter, since state will be optional most of the time the signature could be function updatePath( path, { state, noRouterUpdate } = {} )

@jlongster
Copy link
Member

I'm down with that. Let's go ahead and change the API to pushPath and replacePath. Does that sound good? Or "route" instead of "path".

@MattKunze
Copy link

Matching the naming scheme used by history makes the most sense to me, but it sounds like they might be renaming things as well (to just push and replace) so who knows.

@jlongster
Copy link
Member

Yeah, that's what Ryan said. Also I don't think pushState really says anything about routing outside of react-router, so seeing that action in the wild isn't the best name IMHO, but push and replace are even more vague. I don't think there's anything wrong adding more semantics into the name, and they obviously map to push/replace.

@jlongster
Copy link
Member

I just landed the new sync logic. Can you rebase?

@jlongster
Copy link
Member

And also add tests!

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

@jlongster Great — I'll rebase and fix the tests asap

@jlongster jlongster mentioned this pull request Nov 25, 2015
@ellbee
Copy link
Member

ellbee commented Nov 25, 2015

I think this PR will reintroduce the problem with devtools where a 'RESET' action will change the path to '/' regardless of the initial URL. In my opinion the benefits of landing this outweigh this devtools regression, but it would be nice if we could figure out a way round it.

@ellbee
Copy link
Member

ellbee commented Nov 25, 2015

This is the PR where it was originally "fixed" (modulo my typo of not quoting undefined) #6

@jlongster
Copy link
Member

@ellbee that's true, I didn't notice we lost that check. Should be easy to add back in the check to see if we have a window. However, I've been thinking that getting the URL from window.location isn't the best either. Because if you are using hash history you just want to get /foo, not /#/foo?_key=blah.

Maybe what we should do is set initialState to null/false/etc, but in the initial history.listen call (the listener is always called immediately when you add a listener) we do initialState = { path: locationToString(location), ... } and change the initialState. We wouldn't be mutating the object, we would just define it with let so we could override it later.

@jlongster
Copy link
Member

Although I guess we'd have to keep track if we've set the initialState or not and not do it multiple times... I don't love it, but history does not have a way to get the "current location".

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

@jlongster Rebased and added tests. I also fixed a bug with avoidRouterUpdate. Let me know what you think.

(I thought about cleaning up a couple of things in the tests, but I'll do that in a follow-up PR — this is already a big change)

function locationToString(location) {
return location.pathname + location.search + location.hash;
function locationsAreEqual(a, b) {
return a.path === b.path && deepEqual(a.state, b.state);
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure we need to deepEqual here? I'm having a hard time wrapping my head around this, but probably because I haven't use that state much.

Hm, I have a thought... read my 2nd comment below.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jlongster
Copy link
Member

Thanks a bunch for this, it's awesome! I'll try to merge it soon, just wanted to look through it once more. It is thanksgiving also :)

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

@jlongster Thanks for the comments — I'll take a look and try to get it fixed without the deep-equal :)

@jlongster
Copy link
Member

What was the bug with avoidRouterUpdate btw?

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

@jlongster The bug: kimjoar@a0d6945

It's specified as updatePath(path, avoidRouterUpdate), but used as an object updatePath(routePath, { avoidRouterUpdate: true }).

Btw, pushed a test that would fail if we remove the locationsAreEqual check without other changes (too many store updates plus it changes replace -> push in the store). I'll look at ways of removing locationsAreEqual

@ellbee
Copy link
Member

ellbee commented Nov 25, 2015

Although I guess we'd have to keep track if we've set the initialState or not and not do it multiple times... I don't love it, but history does not have a way to get the "current location".

Ok, thanks. That sounds like a good plan.

@jlongster
Copy link
Member

Thanks all. I have to leave and it's Thanksgiving so I'm going to be slow to reply over the next day or two. I'm happy to merge this in with deep-equal for now and then we can look at it later as well. @kjbekkelund is this ready to merge if we just go with deep-equal for now?

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

@jlongster Everything looks ok when testing in my app, so it should be ready to merge. Have a great Thanksgiving!

@kimjoar kimjoar mentioned this pull request Nov 25, 2015
@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 25, 2015

I found a way to remove deep-equal. I think we need to be sure it's the right way to go, so it should be its own PR (e.g. to discuss additional tests etc). I'll create a PR against master when this is merged.

@jlongster
Copy link
Member

Cool! I think I'm going to wait until tomorrow night to merge. We got a lot of attention today and I just don't want to merge something big right before a day when I'm not going to be around, even though it's just the master branch.

@kimjoar
Copy link
Collaborator Author

kimjoar commented Nov 26, 2015

👍 Relax and enjoy Thanksgiving!

Got some ideas to solve deep-equal, but I think we need tests running in browsers to ensure everything still works as expected.

This was referenced Nov 26, 2015
@jlongster
Copy link
Member

Alright let's just merge this now and clean it up over the next few days for a release.

jlongster added a commit that referenced this pull request Nov 27, 2015
@jlongster jlongster merged commit bbe5071 into reactjs:master Nov 27, 2015
@jlongster
Copy link
Member

Thanks a lot for all the work @kjbekkelund and others!

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.

4 participants