Nested React Router path to n level - reactjs

I have a component called <TaskView> that renders some info about a specific task. My tasks are nested so that I would be able to navigate like so /task1/task1-1/task1-1-1... and so on for N (indefinitely).
How should I write a path that would resolve this url ?
To write a path for level 1 nested I would do: <Route path="/task/:p1" component={taskView} />, for level 2 I would do <Route path="/task/:p1/:p2" component={taskView} /> I don't know how deep the task structure would be, so how would I write a path for an undefined number of parameters ?

ReactRouter has a notion of non exact matches. It will attempt to find the best match so you don't need to define all these subroutes to mount the same components.
React : difference between <Route exact path="/" /> and <Route path="/" />
So actually you should be able to do
<Route path="/task/:p1" component={taskView} />
just fine.

Related

React router V3 route does not match if I put one extra letter uppercase

So, I am using react router V3, and surprisingly one detail as little as one uppercase letter makes one route to not match. So this does worl:
<Route
path="payments"
component={AccountBalance}
>
<Route path=":paymentId" component={AccountBalance} />
</Route>
While this doesn't produce any navigation
<Route
path="payments"
component={AccountBalance}
>
<Route path=":paymentID" component={AccountBalance} />
</Route>
The difference is paymentID vs paymentId.
Reading react router v3 docs, there is nothing suggesting that this should happen
The route path must be lowercase, for example, you can use,
<Route path=":payment_id" ... />
for example, in javascript,
let helloWorld;
and
let HelloWorld;
are not equal, becouse theese variables were not written equal.

Route Order With Multiple Dynamic Params

My problem is that i cant figure out the best way to handle multiple dynamic params in a deep link without having to have it fully rely on the order of the Routes in the JSX
I'll start by outline the flow of my app.
List of Television Series -> user clicks series -> List of Episodes in Series -> user clicks episode -> Show stats about episode
after this flow, i want my path to be /series/:series_id/episode/:episode_id.
Currently i have this working by setting up my router basically like so:
<Router>
<Switch>
<Route exact path="/series" component={SeriesLibrary} />
<Route
path="/series/:series_id/episode/:episode_id"
component={Episode}
/>
<Route path="/series/:series_id" component={EpisodeLibrary} />
</Switch>
</Router
but that is relying on the multi-dynamic path (the one with the series_id and episode_id) coming before the one that just has the series_id!
This is because even when the path is series/4356/episode/4567 it would match the series/4356 before ever rendering the Episode component.
Is there a better way for me to address the issue of multiple dynamic deep linked params in react router?
I feel like this cannot be best practice, relying strictly on the order of JSX elements for your app to work?
You can pass exact prop to to EpisodeLibrary:
<Router>
<Switch>
<Route exact path="/series" component={SeriesLibrary} />
<Route exact path="/series/:series_id" component={EpisodeLibrary} />
<Route
path="/series/:series_id/episode/:episode_id"
component={Episode}
/>
</Switch>
</Router>

How do I avoid rendering a component when another component in a similar path has already rendered when using URL params in React Router v4?

I'm trying to create RESTful routes for my application, but I'm having problems when it comes to routes with URL params.
Here are the routes that I want to have:
/accounts
/accounts/new
/accounts/edit
/accounts/:id
These is what my router looks like:
<Router>
<Route exact path="/accounts" component={AccountsList} />
<Route exact path="/accounts/new" component={AccountCreate} />
<Route exact path="/accounts/edit" component={AccountUpdate} />
<Route exact path="/accounts/:id" component={AccountDetail} />
</Router>
/accounts works fine, but when I go to /accounts/new or /accounts/edit, it also renders AccountDetail which is supposed to be located at /accounts/:id.
For the record, that I get that this is the correct behavior since /accounts/:id technically matches /accounts/new and /accounts/edit.
My question is if there's a way to make :id match with a specific pattern only (numbers only).
Try the < Switch> component of reactRouter.
Renders the first child < Route> or < Redirect> that matches the
location.
I think it's exactly what you are looking for.

Match multiple path with react router v4

Given I have 2 path rendering the same component, how do I avoid to repeat route configs like this :
<Route path="/path1" component={MyComp} />
<Route path="/path2" component={MyComp} />
Best solution I found so far (but seems a bit strange) :
<Route path="/:path(path1|path2)" component={MyComp} />
<Route path={["/common-one", "/common-two"]} component={Common} />
For version 5 above
https://reactrouter.com/web/api/Route
Great answer. This also helps in the following scenario:
<Route path="/path/path1" component={MyComp} />
<Route path="/path/:subpath(path2|path3)" component={MyAnotherComp} />
Without (path2|path3) both components MyComp and MyAnotherComp are mounted if the path is /path/path2.
PS. Would have added as a comment, but not eligible :).
If you need to allow multiple match (different parameters) but also without parameter - e.g. match URLs:
/questions
/questions/posted
/questions/answered
You can do this with optional parameter (note question mark after the bracket)
<Route path="/questions/:tab(posted|answered)?" component={...} />

Unit testing route matching with React Router 2

I’m trying to add unit tests for a React application and would like to test the routes provided by React Router (2.0.1). I’d like to test whether specific paths that I supply will match a route. I am writing my tests using Mocha and expect.
I’ve looked through the documentation on the React Router repository, but the only testing guide I could see was explaining how to test a <Link /> and how it’s rendered.
Say I have the following code:
// import statements omitted for brevity
export const routes = (
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="/foo">
<IndexRoute component={FooIndex} />
<Route path="add" component={FooAdd} />
<Route path=":fooId" component={FooDetails} />
</Route>
</Route>
)
ReactDOM.render(
<Router history={browserHistory}>{routes}</Router>,
document.getElementById('app')
)
How can I test that the routes created in the routes variable would match the following:
/
/foo
/foo/add
/foo/25
But not routes like:
/foo/bar/12
/bar
Essentially I want to check that every expected URL format has a route that will match it and that unexpected URLs don't match any routes.
I’m not interested in the elements that are rendered by the routes, so don't want to base my tests on checking whether a specific thing is rendered, only that a matching route was found and preferably some way of checking that it was in fact the expected route (I'd guess checking what the name of the component is or something?)
Any help is gratefully appreciated.
Thanks
We test exactly this in our test for matchRoutes: https://github.com/ReactTraining/react-router/blob/v3/modules/__tests__/matchRoutes-test.js
You can follow this pattern. If you can't identify your routes by reference, you can indeed assert on the components that were rendered as well.
As matchRoutes isn't exported, you'll want to use the match helper (otherwise used for for server-side rendering) instead, and check renderProps.routes or renderProps.components.

Resources