I'm using the sidebar example provided in the official documentation of react-router-v4 as an inspiration https://reacttraining.com/react-router/web/example/sidebar
1- So the initial URL of my application would be : localhost:3000/search-page/Lists
2- I have a list of clickable Links that when clicked display the clicked data on the sidebar, and when this happens the URL gets updated : localhost:3000/search-page/Lists/itemList1selected
3- I then press on the button "Show List number 2" to display a new list
4- my goal is using nested routes, when I click on a Link from "List number 2". it would append it below the item selected from "List number 1" ... and update the URL at the same time : localhost:3000/search-page/Lists/itemList1selected/itemList2selected
here's my current code :
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
showListButtonPressed: true
};
this.showTheOtherList = this.ShowTheOtherList.bind(this);
}
showTheOtherList() {
this.setState({
showListButtonPressed: !this.state.showListButtonPressed
});
}
render() {
const dataList1 = dataFromDataBase
.allItemsFromList1()
.map(list1 => ({
path: `${this.props.match.params.type}/${list1.id}`,
mainList1: () => (
<div>
{`${list1.company} ${list1.name} ${list1.price}`}
</div>
),
sidebarList1: () => (
<div>
<h3>item List 1 selected</h3>
{list1.company}
</div>
)
}));
const dataList2 = fakeFlightApiDataTesting
.allItemsFromList2()
.map(list2 => ({
path: `${this.props.match.params.type}/${list2.id}`,
mainList2: () => (
<div>
{`${list2.company} ${list2.name} ${list2.price}`}
</div>
),
sidebarList2: () => (
<div>
<h3>item List 2 selected</h3>
{list2.company}
</div>
)
}));
return (
<div style={{ display: 'flex' }}>
<div style={{ width: '20%' }}>
{dataList1.map(route => (
<div>
<Route
key={route.path}
path={`/search-page/${route.path}`}
exact={route.exact}
component={route.sidebarList1}
/>
</div>
))}
{dataList2.map(route => (
<div>
<Route
key={route.path}
path={`/search-page/${route.path}`}
exact={route.exact}
component={route.sidebarList2}
/>
</div>
))}
</div>
<div>
// Switch the lists when button is pressed
{this.state.showListButtonPressed ? (
<div>
<ul>
{dataList1.map(route => (
<li key={route.path}>
<Link to={`/search-page/${route.path}`}>
{route.mainList1()}
</Link>
</li>
))}
</ul>
<button onClick={this.showTheOtherList}>
Switch Lists
</button>
</div>
) : (
<div>
<ul>
{dataList2.map(route => (
<li key={route.path}>
<Link to={`/search-page/${route.path}`}>
{route.mainList2()}
</Link>
</li>
))}
</ul>
<button onClick={this.showTheOtherList}>
switch Lists
</button>
</div>
)}
</div>
</div>
);
}
}
here are some screenshots to have a better idea :
Nested Routes in React Router We will continue working on the User component, because this is the place where we want to have the nested routing via tabs. Therefore, we will instantiate a new set of Link components (which will be our unstyled tabs) which navigate a user to their profile and their account.
jsx import the required components: import { BrowserRouter as Router, Routes, Route } from "react-router-dom" . It is standard practice to import BrowserRouter as Router because BrowserRouter is too long to type!
To recap, nested routes allow you to, at the route level, have a parent component control the rendering of a child component. Twitter's /messages route is the perfect example of this. With React Router, you have two options for creating nested routes.
The difficult part is that since you're using 2 path params, it doesn't function exactly the same as the example they use. Let's say you have "n" list1 options, and "m" list2 options. That means you would n x m total routes. For it to work like this, you would need to create a list2 route combined with every list1 option. Then the path
key for list2 would look something like ${this.props.match.params.type}/${list1.id}/${list2.id}
. I think this could also be achieved this by making the path for list2 ${this.props.match.url}/${list2.id}
, but it would require that the list1 is always selected first.
It's a pretty tricky case, but I hope that helps
You can use different approaches to solve this:
Using this pattern you can create deeply nested lists, more than 2 levels deep.
<SidebarRoute />
for that case, passing second level seleted item as a prop.I would suggest you (3rd option) to hold selected items in state, and render accordingly in sidebar. This option will work out just fine, if you are not obligated to send links by e-mail or something, just want to render. Then you can save UI state in the store of your choice (redux, flux, you name it).
Basic example for 2nd approach (idlvl2 is what you are trying to show in sidebar): https://codesandbox.io/s/o53pq1wvz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With