I'd like to render some of my routes within my public layout, and some other routes within my private layout, is there a clean way to do this?
Example that obviously doesn't work, but I hope explains roughly what I'm looking for:
<Router>
<PublicLayout>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
</Switch>
</PublicLayout>
<PrivateLayout>
<Switch>
<Route exact path="/profile" component={ProfilePage} />
<Route exact path="/dashboard" component={DashboardPage} />
</Switch>
</PrivateLayout>
</Router>
I'd like the layout to switch for certain routes, how do I do this with the new react router?
Nesting routes no longer works and gives me this error:
You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored
Edit: Having layouts wrap entire groups of routes also means those layouts are only rendered once as long as you stay in the same private/public group of routes. This is a big deal if your layout has to fetch something from your server for example, as that would happen on every page change if you wrap each page with a layout.
What I have done for this is create a simple component that adds an extra property to the Route component which is layout:
function RouteWithLayout({layout, component, ...rest}){
return (
<Route {...rest} render={(props) =>
React.createElement( layout, props, React.createElement(component, props))
}/>
);
}
Then in your case your routes would look like this
<Switch>
<RouteWithLayout layout={PublicLayout} path="/" component={HomePage}/>
<RouteWithLayout layout={PublicLayout} path="/about" component={AboutPage}/>
<RouteWithLayout layout={PrivateLayout} path="/profile" component={ProfilePage}/>
<RouteWithLayout layout={PrivateLayout} path="/dashboard" component={DashboardPage}/>
</Switch>
UPDATE 2020
Well for now I'm following this approach, it's simpler that the one I posted before:
const Pages = () => {
return (
<ReactRouter>
<Switch>
<Route path="/comingsoon" component={ComingSoon} exact />
<Route>
<MainLayout>
<Switch>
<Route path="/home" exact>
<Home />
</Route>
<Route path="/login" exact>
<Login />
</Route>
<Route path="/useraccount" exact>
<UserAccount />
</Route>
<Route path="/createaccount" exact>
<CreateAccount />
</Route>
<Route path="/contact" exact>
<Contact />
</Route>
<Route path="/about" exact>
<About />
</Route>
<Redirect path="/" exact to="/comingsoon" />
<Route path="*" exact component={NotFound} />
</Switch>
</MainLayout>
</Route>
</Switch>
</ReactRouter>
);
};
In this way, the MainLayout will take care of everything except for the coming soon page.
OLD ANSWER
If you are using Typescript and want to follow this react layout aproach then you can declare your layout like this:
import './Default.less';
import React from 'react';
import { Route } from "react-router-dom";
import { Sider } from './Components';
import { Notification } from 'Client/Components';
interface IDefaultProps {
component: any
path?: string;
exact?: boolean;
}
const Default: React.SFC<IDefaultProps> = (props) => {
const { component: Component, ...rest } = props;
return <Route {...rest} render={matchProps => (
<div className="defaultLayout">
<Sider />
<div className="defaultLayoutContent">
<Component {...matchProps} />
</div>
<Notification />
</div>
)} />
}
export default Default;
And declare routes like this:
import React from 'react';
import { Route } from 'react-router-dom';
import { DefaultLayout } from 'Client/Layout';
import { Dashboard, Matters, Schedules, Students } from './Containers';
export const routes = <div>
<DefaultLayout exact path="/" component={Dashboard} />
<DefaultLayout path="/matters" component={Matters} />
<DefaultLayout path="/schedules" component={Schedules} />
<DefaultLayout path="/students" component={Students} />
</div>;
After looking for it, the clean and efficient way (avoiding abusive re-rendering):
<Route exact path={["/about", "/"]}>
<PublicLayout>
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
</PublicLayout>
</Route>
<Route path={["/profile", "/dashboard"]}>
<PrivateLayout>
<Route path="/profile" component={ProfilePage} />
<Route path="/dashboard" component={DashboardPage} />
</PrivateLayout>
</Route>
aslo, It can be refactored, see my complete answer: https://stackoverflow.com/a/57358661/3437790
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