Reputation: 138
I'm new in React and doesn't know how to create List and Detail view using React Router DOM. Some how I created it but I know this is not a good way to do it. If you look into below code, you will find it will always reload the whole page if I select another campaign. What will be the good way to do it. Please help...
App.js
<Switch>
<Fragment>
<PrivateRoute exact path="/admin/campaigns/:id" component={CampaignComponent}/>
<PrivateRoute exact path="/admin/campaigns/:id/messages" component={CampaignComponent}/>
<PrivateRoute exact path="/admin/campaigns/:id/contacts" component={CampaignComponent}/>
</Fragment>
</Switch>
Campaign.js
let layout;
switch (props.match.path) {
case '/admin/campaigns/:id':
layout = <CampaignDetailComponent props={props}/>;
break;
case '/admin/campaigns/:id/messages':
layout = <CampaignMessageListComponent props={props}/>;
break;
case '/admin/campaigns/:id/contacts':
layout = <CampaignContactListComponent props={props}/>;
break;
default:
layout = <div/>;
}
return (
<div>
<div className="col-6">
<CampaignListComponent props={props}/>
</div>
<div className="col-6">
{layout}
</div>
</div>
)
So, in the first col-6
I want to show the list of Campaigns and in second col-6
I want to render the components as per route change.
You can follow this link to see the actual working code sample that demonstrate this issue.
Upvotes: 1
Views: 6320
Reputation: 203208
You have your "navigation" coupled to your page UI.
Split out the rendering of your links in the left section from the content in the right section. The rest of the changes a centered around computing paths and route structuring.
App.js
Render the campaign list container and navigation on its own route. This is so the nested links can inherit from the route path.
import React, { Component } from "react";
import { HashRouter, Redirect, Route, Switch } from "react-router-dom";
import CampaignComponent from "./Campaign/Campaign";
import CampaignListComponent from "./Campaign/Components/CampaignList";
import "./styles.css";
class App extends Component {
render() {
return (
<div className="App">
<h3>Sample app to demonstrate React Router issue</h3>
<HashRouter>
<div className="campaign-container">
<div className="campaign-list">
<Route path="/admin/campaigns">
<CampaignListComponent />
</Route>
</div>
<div className="campaign-detail">
<Switch>
<Route path="/admin/campaigns" component={CampaignComponent} />
<Redirect from="*" to="/admin/campaigns" />
</Switch>
</div>
</div>
</HashRouter>
</div>
);
}
}
Campaign list component
import React, { useState } from "react";
import { Link, generatePath, useRouteMatch } from "react-router-dom";
const CampaignListComponent = () => {
const [campaignList, setCampaignList] = useState([
{ id: 1, name: "Campaign1" },
{ id: 2, name: "Campaign2" },
{ id: 3, name: "Campaign3" },
{ id: 4, name: "Campaign4" },
{ id: 5, name: "Campaign5" }
]);
const { url } = useRouteMatch();
return (
<div style={{ width: "90%" }}>
{campaignList.map(({ id, name }) => (
<div className="campaign-list-item" key={id}>
<Link to={generatePath(`${url}/:id`, { id })}>{name}</Link>
</div>
))}
</div>
);
};
Campaign component
import React from "react";
import { Route, Switch, useRouteMatch } from "react-router-dom";
import CampaignMessageListComponent from "./Components/CampaignMessageList";
import CampaignDetailComponent from "./Components/CampaignDetail";
import CampaignContactListComponent from "./Components/CampaignContactList";
const CampaignComponent = () => {
const { path } = useRouteMatch();
return (
<div className="campaign-list">
<Switch>
<Route
path={`${path}/:id/messages`}
component={CampaignMessageListComponent}
/>
<Route
path={`${path}/:id/contacts`}
component={CampaignContactListComponent}
/>
<Route path={`${path}/:id`} component={CampaignDetailComponent} />
</Switch>
</div>
);
};
Content components
Contact
import React from "react";
import { useHistory } from "react-router-dom";
const CampaignContactListComponent = () => {
const history = useHistory();
return (
<div className="row">
<p>Campaign Contact List</p>
<button onClick={history.goBack}>Go Back</button>
</div>
);
};
Message
import React from "react";
import { useHistory } from "react-router-dom";
const CampaignMessageListComponent = () => {
const history = useHistory();
return (
<div className="row">
<p>Campaign Message List</p>
<button onClick={history.goBack}>Go Back</button>
</div>
);
};
Detail
import React from "react";
import { Link, useHistory, useParams, useRouteMatch } from "react-router-dom";
const CampaignDetailComponent = () => {
const { id } = useParams();
const { url } = useRouteMatch();
const history = useHistory();
return (
<div>
<h6>Campaign Detail</h6>
<p>You have selected Campaign - {id}</p>
<button>
<Link to={`${url}/messages`}>Goto Messages</Link>
</button>
<button>
<Link to={`${url}/contacts`}>Goto Contacts</Link>
</button>
<button onClick={history.goBack}>Go Back</button>
</div>
);
};
Upvotes: 5