Reputation: 9177
I'm not sure if I'm approaching this in the right way at all, so a bit of background first:
Let's say I have countries and cities in each country that I'm going to fetch from two stores, CountryStore and CityStore in the topmost route (view1). I'm trying to set up react-router so that I have nested routes like this:
<Route name="app" path="/" handler={App}>
<DefaultRoute name="view2" handler={View2}/>
<Route name="view1" path='country/:countryId' handler={View1}>
<DefaultRoute name="view3" handler={View3}/>
<Route name="view4" path='city/:cityId' handler={View4}/>
< More nested routes />
</Route>
</Route>
So from what I've been reading up on, I've understood that I should have state in my top view1 and pass everything down as props to view3, view4 and any others.
So here's a fiddle where I've got things working by passing down props with the route handler in view1, and from links I'm passing params based on which each view can filter out what they need. But I'm wondering if there's a smarter way of doing this by passing down the props I'm going to need with each link somehow. Meaning that if in my city list I'm already iterating through all the city objects, can I with the city link pass down the current city as props somehow, so the city view wouldn't need to filter out its city each time?
I hope the question is clear enough, I'm thankful for any advice!
Upvotes: 2
Views: 1469
Reputation: 159095
Your question is a little confusing (maybe because of the very generic variable/view names), but I think I see what you're getting it.
I think there are two parts of the answer: can you do this, and should you do this.
I believe it's definitely possible that you can do what you're suggesting. If you look at the params in View1
, you can see that when the url is country/1
the params are { countryId: "1" }
, but when the url is country/1/city/2
, the params are { countryId: "1", cityId: "2" }
. So, based on this, View1
could see the cityId
param and decide to pass an additional property to its child, for example:
// In View1
var props = {
country: testCountry
}
if (this.props.params.cityId) {
props.city = (get the city object here);
}
return (
<div>View 1 wrapper: countryId {countryId}
<RouteHandler {...this.props} {...props}/>
</div>
);
However, I'm not really sure that you should. This is breaking the encapsulation provided by React Router; you're coupling two views by giving View1
direct knowledge about how one of its children, View4
, works.
If you're really concerned about the performance hit of iterating over the cities more than once, it may be worthwhile to provide an ID-indexable data structure that View4
can use to look up the city directly (e.g. var city = this.props.whatever[this.props.params.cityId]
).
Taking a step back, I personally thing the "get all the state and pass it down as props" that Bill describes in the answer you linked to might break down a bit in applications that rely on routing. I consider each view passed to the router via <Route handler={...} />
to be a view-controller—a miniature standalone app, as it were. Doing so, as Bill mentions, gives a better encapsulation of the domain that the route/route handler is dealing with, and I don't think that it makes debugging more difficult, as the routes declare exactly which view is acting as the top-level view-controller for any given URL (so if some data looks wrong you just go immediately to the view-controller for the current route).
If you use a nice composition strategy to connect your route handlers to flux stores (see the code at this Fluxxor issue as an example), it makes it even clearer how the data gets from the stores into the components.
Upvotes: 2