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

Make params available to getChildRoutes providers #3556

Merged

Conversation

avanderhoorn
Copy link
Contributor

As it says on the label, this is an initial POC of making params and remainingPathname available to getChildRoutes providers. This was instigated primarily via a discussion with @taion and a another minor discussion with @timdorr.

Use Case
The use case this is intended to help with is in cases where the child route to be returned by getChildRoutes is dependent on the params that have been evaluated so far. For instance, if I have :country as the path for the current route being matched, in the getChildRoutes function for that route, I want to be able to access the country param so that I can decide which child route should be returned for that country (it can be different in different cases). Additionally, I have other cases where I want to "read forward" into remainingPathname of the path to decide what child route should be returned. The later being a more minor use case.

Currently, without this patch, the only context I have available is the location arg, which is not that useful and which I end up having to parse manually. This is doable, but is tedious and leads to very brittle code (i.e. if you add/remove "upstream" path segments).

Approach
As discussed with @taion, this PR has been done in a "non breaking" fashion - it follows the same pattern as a similar commit which was done to getComponent - here. This is done by making all the location properties available at the root level for non dev builds but adding warnings to usage of those properties in dev builds (again following the same logic as with getComponent).

At the time of calling getChildRoutes we have access to the current params that have been available (which is what I am primarily after) and the remainder of the path that needs to yet to be parsed. As such, a state object is created with these values, plus the additional location properties, and passed into the registered getChildRoutes.

Questions

  • progressState vs nextState - Elsewhere in the system, this object is called nextState, I wasn't sure you would consider if this exactly matches the semantics at play here since technically its not the "final" state and doesn't match the same structure as the current nextState. Hence I have called this progressState. Do you agree with this, is there a better name or should it just be nextState?

Note
I have abstracted out the deprecateLocationProperties function from getComponents as the logic is exactly the same. I'm assuming this is appropriate/desirable.

Work to be done
Assuming we are good with this PR and/or get to a point where we are good with it, I will finish off the, tests, samples update, docs, etc (inline with the work that was done with the getComponent commit mentioned earlier).

@timdorr
Copy link
Member

timdorr commented Jun 20, 2016

I think this looks good. It just needs tests and docs updates, as you've pointed out.

Keep in mind a lot of this is obsoleted by 3.0, which we should have ready to go in a few weeks. But if the upgrade path turns out to be too difficult or burdensome (which is going to be inevitable, as it involves some major API changes), then it will be good to include this in 2.0 so you're not forced to upgrade for one minor feature.

@taion
Copy link
Contributor

taion commented Jun 20, 2016

Let's try our best to minimize API changes for the less advanced functionality... the getComponents API ought to be replaced (and we have other issues discussing that), but we should e.g. try not to break people using synchronous route configs with basic routing and maybe one or two middlewares.

@avanderhoorn
Copy link
Contributor Author

@timdorr Is there anything that talks about whats going to be in v3, etc? I can see some pr's against the v3 milestone, but it doesn't give much of a picture of whats happening or what the scope is.

@taion Was that comment directed at me and this pr? Are you saying that this is ok?

@timdorr
Copy link
Member

timdorr commented Jun 20, 2016

Nope, Ryan and Michael are still finalizing things and don't want to go public until things are rock solid (which more important given the visibility of this project).

@avanderhoorn
Copy link
Contributor Author

Ok. So given that you probably know more than me about whats coming, do you think its worth the effort to finish this off still?

@@ -160,7 +162,19 @@ function matchRouteDeep(
}
}

const result = getChildRoutes(route, location, onChildRoutes)
const progressState = {
Copy link
Contributor

Choose a reason for hiding this comment

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

In most cases the route will not use this object; no reason to do stuff like call createParams unless we know we need to call getChildRoutes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok so you would like the call to createParams shifted to between lines 15-18?

@timdorr
Copy link
Member

timdorr commented Jun 20, 2016

@avanderhoorn Yes, definitely. For those that don't want to or can't upgrade to 3.0, but would need something like this.

@avanderhoorn
Copy link
Contributor Author

Ok great!

@avanderhoorn
Copy link
Contributor Author

@taion I've updated given your feedback. Does this look like what you where thinking?

@avanderhoorn
Copy link
Contributor Author

Also are we happy with the usage of progressState before I start going through and updating things elsewhere?

if (route.childRoutes) {
return [ null, route.childRoutes ]
}
if (!route.getChildRoutes) {
return []
}

let sync = true, result
let sync = true, result, progressStateWithLocation
const progressState = {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would call this partialNextState – we use the term elsewhere for partial next state.

Can we omit remainingPathname here? I don't think it makes sense to pass down at this point. It feels odd for child routes to explicitly depend on the not-yet-matched portion of a route.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

partialNextState is fine.

@taion
Copy link
Contributor

taion commented Jun 20, 2016

This is great. LGTM. Thanks.

@avanderhoorn
Copy link
Contributor Author

Added unit test here. I think thats everything. Any feedback?

@@ -332,6 +332,35 @@ describe('matchRoutes', function () {
})
})

describe('a nested route with a getChildRoutes callback', function () {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you combine this with the previous describe() block? They're really covering the same thing.

@timdorr
Copy link
Member

timdorr commented Jun 20, 2016

👍

@avanderhoorn
Copy link
Contributor Author

Ok I think this is the final update.

@avanderhoorn avanderhoorn changed the title Make params & remainingPathname available to getChildRoutes providers Make params available to getChildRoutes providers Jun 21, 2016
@avanderhoorn
Copy link
Contributor Author

The value of state persists between test invocations, which could lead to potential problems. Instead use createSpy and assert on spy.calls[0].arguments[0].

Can you show me how you would like this done in this context?


beforeEach(function () {
getChildRoutes = function (location, callback) {
getChildRoutes = function (partialNextState, callback) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Use expect.createSpy here: https://github.com/mjackson/expect#spies

You can then assert on getChildRoutes.calls[0].arguments[0]

@avanderhoorn
Copy link
Contributor Author

Ok I think thats it

@taion
Copy link
Contributor

taion commented Jun 21, 2016

This is fine – I'll resolve the remaining test issues myself.

@reactjs/routing Are we okay with cutting a maintenance 2.5.0 with this change?

@taion taion merged commit c1167fb into remix-run:master Jun 21, 2016
taion added a commit that referenced this pull request Jun 21, 2016
@avanderhoorn
Copy link
Contributor Author

Thanks for your help @taion. Looking at that test, it now makes sense. Also rolling it out to the other APIs is a plus. Regarding the refactoring, I was going to do that, but thought it was a bigger change and was wanting to get the core concept in first.

timdorr pushed a commit that referenced this pull request Jun 21, 2016
@lock lock bot locked as resolved and limited conversation to collaborators Jan 19, 2019
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.

3 participants