React-router: Requesting to be able to merge parent's params into child component in nested Route scenario.

Created on 28 Apr 2017  路  4Comments  路  Source: ReactTraining/react-router

Version

4.0.0

Feature

I noticed in express 4 docs:
express.Router() has an option mergeParams which you can set to true, so that it will:
"Preserve the req.params values from the parent router."

What I'm requesting of react-router is similar stuff.
I love nested Routes style that get your code in order, if your url has a lot of params(/:projectId/:taskId). But if I do so, the component in nested Route will not have access to parents' params, here's an example:

Route design is:

/:projectId/ -> List

/:projectId/:taskId -> Detail

code example:

<Route path='/:projectId' component={Project} />

and

const Project = ({ match }) => <Switch>
 <Route path={match.url} component={List} />
 <Route path={`${match.url}/:taskId`} component={Detail} />
</Switch>

I can't read projectId inside <Detail />and all the children components of it, but some functionality inside does depend on projectId.

So basically if I want to use nested Routes style, I can still read the whole url as it is, but I won't be getting match.params values from the parent Route.

If I visit /3/2, <Detail /> component can still get access url by location.pathname, but match.params will only have { taskId:2 }.

It feels unnatural that a child component knows /3/2 but not projectId = 3.

So I'm requesting that we can somehow get access to parent's params like similar option given by express 4 routers.

Most helpful comment

match.path is the path-to-regexp style path, while match.url is the matched portion of the location.pathname.

const match = {
  path: '/:projectId',
  url: '/2'
}
const pathPath = `${match.path}/:taskId` // /:projectId/:taskId
const urlPath = `${match.url}/:taskId` // /2/:taskId

If you use the first, then the parent params will be included in the child route's params object. In the second, they won't because the path does not include the param string (:projectId) for path-to-regexp to parse.

As I stated above, once relative routes land this is not something that you will have to think about, but using match.path works for now.

All 4 comments

This will be easier once relative routes are supported, but for the time being you should use match.path instead of match.url.

<Route path={`${match.path}/:taskId`} component={Detail} />

@pshrmn Is there no solution to this? I do not see how the above response solves this.

match.path is the path-to-regexp style path, while match.url is the matched portion of the location.pathname.

const match = {
  path: '/:projectId',
  url: '/2'
}
const pathPath = `${match.path}/:taskId` // /:projectId/:taskId
const urlPath = `${match.url}/:taskId` // /2/:taskId

If you use the first, then the parent params will be included in the child route's params object. In the second, they won't because the path does not include the param string (:projectId) for path-to-regexp to parse.

As I stated above, once relative routes land this is not something that you will have to think about, but using match.path works for now.

One thing to note is that <Redirect />s should still use match.url.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ArthurRougier picture ArthurRougier  路  3Comments

ryansobol picture ryansobol  路  3Comments

Waquo picture Waquo  路  3Comments

winkler1 picture winkler1  路  3Comments

maier-stefan picture maier-stefan  路  3Comments