Any help would be appreciated, So i have a page with Header, Sidebar, Footer and Main, where Sidebar has static links, which when clicked display the components. The issue here is on clicking the links, sidebar,header and footer are re-rendering which is not required. I have tried shouldComponentUpdate in sidebar but it won't work. Versions used by the project: "react": "^16.12.0", "react-dom": "^16.12.0", "react-router-dom": "^5.1.2", I'll be here till this issue is resolved so feel free to ask any question
here is myApp.js (the root file)
function App() {
return (
<Provider store={Store}>
<Router history={history}>
<AppRoutes />
</Router>
</Provider>
);
}
now the AppRoutes component has following method
const RouteList = [
{
path: "/",
component: Dashboard,
guest: false,
exact: true
},
{
path: "/security_info",
component: SecurityInfoPage,
guest: false,
exact: true
},
]
class AppRoutes extends Component {
componentDidMount() {
...here we fetch the login info from store
isAuthenticated = true
}
render() {
...if it has access token, it
return (
<Switch>
{RouteList.map((route, i) => (
route.guest === false
? <PrivateRoute isAuthenticated={isAuthenticated} key={i} {...route} />
: <AppRoute key={i} {...route} />
)
)}
</Switch>
);
}
}
as is_authenticated is true, it goes to private route inside AppRoute.js file
const PrivateRoute = ({isAuthenticated, component: Component, ...rest }) => (
<Route
{...rest}
render={(props) => (
isAuthenticated === true
? <DashboardLayout>
<Component {...props}/>
</DashboardLayout>
: <Redirect to='/login' />
)}
/>
)
it goes to dashboardlayout where it has multiple components
<div className={'wrapper'}>
<Navigation />
<div className="page-content">
<Sidebar />
<div className="content-wrapper">
{children}
<MessageSideBar />
<Footer />
</div>
</div>
</div>
Now as i click on a different link, it goes to dashboard layout where its prop children gets changed rendering the entire dashboard including header, footer, sidebar. Edit 1: Here is the Sidebar file
class Sidebar extends Component {
componentDidMount = () => {
it is requesting data from 3 api's
this.props.dispatch(sidebarAction.sidebarDetail())
this.props.dispatch(settingAction.getCreditAmount())
this.props.dispatch(messageAction.getUnReadMessageCount())
}
render(){
return(
<ul>
<li>
<NavLink
exact={true}
to="/" >
<span>Dashboard</span>
</NavLink>
</li>
<li>
<NavLink to="/security_info">
<span>Security Information</span>
</NavLink>
</li>
</ul>
)}
Though there are like 10+ NavLinks but i have included only 2 and also removed irrelevant classnames
Your routes are structured like the following snippet, which will cause rerendering the Dashboard
component every time you switch the route.
<Route path="/subComponent" component={SubComponent}/>
const SubComponent = () => {
return (
<Dashboard>
// Here is your content place
</Dashboard>
)
}
However, the correct solution would be to put the routes directly inside the Dashboard
component where you would like to render your components wrapped by the layout (Dashboard
) like this:
<Dashboard>
<DashboardMenu>
<SideNav /> // e.g. containing links with history.push()
</DashboardMenu>
// here is the place where the components wrapped by the layout should be rendered, so place the routes here
<Route path={...} component={() => <ComponentInsideDashboard />}
</Dashboard>
You should render the actual content (the dynamic one, not the static Dashboard
) already inside the Dashboard. Since every route returns the dynamic components wrapped inside Dashboard
, the Dashboard
will get rendered multiple times.
To put it even more simply: Since you want the Dashboard
to get rendered only once, there should just be only one place where you are using it.
If you also want to render content without a layout (Dashboard
) or multiple different ones, you can simply make use of nesting routes.
export const BaseApplicationRoutes = () => {
return (
<BrowserRouter>
<Switch>
<Route path="/dashboard1" component={<Dashboard1 />}/>
<Route path="/dashboard2" component={<Dashboard2 />}/>
<Route path="/noDashboard" component={<NoDashboard />}/>
</Switch>
</BrowserRouter>
)
}
<Dashboard1> // Dashboard2 could also look like this
<Dashboard1Menu>
<SideNav /> // e.g. containing links with history.push()
</Dashboard1Menu>
// Routes containing dynamic content
<Route path={...} component={() => <ComponentWithDashboard1 />}
</Dashboard1>
<NoDashboard>
// any content or even more routes rendering content without a layout
</NoDashboard>
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