I have come across several scenarios where I needed to create views/pages that had different layout structures in real-time applications like real estate, eCommerce. Recently I had the opportunity to create a multi-layout application and just want to share it.
Initial setup
Create a simple React app that changes depending on the current route:
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import Router from "components/router";
const MyApp = props => (
<BrowserRouter>
<Router />
</BrowserRouter>
);
ReactDOM.render(<MyApp />, document.getElementById("app"));
javascript
The component defines all the possible routes of our app and their corresponding components:
import React from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import { LoginPage, UserDetailsPage } from "pages";
const Router = () => (
<Switch>
<Redirect from="/" to="/layout1"/>
<Route path="/layout1" component={LoginPage} />
<Route path="/layout2" component={UserDetailsPage} />
</Switch>
);
export default Router;
Next step, Create two different layout files(DashboardLayout.js, LoginLayoutRoute.js ) and their respective routes to implement multiple layouts.
LoginLayoutRoute.js
import React from 'react';
import { Route } from 'react-router-dom';
const LoginLayout = ({ children }) => (
<div>
{children}
</div>
);
const LoginLayoutRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={props => (
<LoginLayout>
<Component {...props} />
</LoginLayout>
)} />
)
};
export default LoginLayoutRoute;
DashboardLayout.js
import { Route } from 'react-router-dom';
const DashboardLayout = ({ children, ...rest }) => {
return (
<div className='page page-dashboard'>
<header>
<h1>Dashboard</h1>
<p>The agent dashboard has 3 parts, a side menu, a top bar and content area to render components.</p>
</header>
<section>
<nav>
<p>
DashboardLayout.js contains a higher order component (HOC) that
takes a component as a prop and passes it into a `Route` from
react-router-dom.
</p>
<p>
The specific path for the component being passed to the HOC is
passed to the Route in the spread ...rest .
</p>
</nav>
<article>{children}</article>
</section>
<footer>
<p>Footer</p>
</footer>
</div>
);
};
const DashboardLayoutRoute = ({ component: Component, ...rest }) => {
return (
<Route
{...rest}
render={(props) => (
<DashboardLayout>
<Component {...props} />
</DashboardLayout>
)}
/>
);
};
export default DashboardLayoutRoute;
Both Login & Dashboard Layout contains a higher-order component (HOC) that takes a component as a prop and passes it into a Route
from react-router-dom. The specific path for the component being passed to the HOC is passed to the Route in the spread ...rest.
A child component will be rendered at {children} and the rest of the elements will remain the same for all the child components that are using this layout.
As we can see here, by changing the route, different master pages are rendered for different components in DOM.
The finished code can be found on github.
Happy coding!
Top comments (6)
freaking wired while vue multi layouting is so simple
Can you please help where should i add those layout routes at the app architecture? i mean at the pages folder or components for instance?
i believe it should not be neither page nor components .
Appreciate your help.
You can put them anywhere. In most cases with MVC you'd have a
views
directory with alayouts
directory inside of it, but it's really up to you.could you share LoginPage page , please
hey what if I like to create a child route inside the dashboard
The Root component will be responsible for rendering all Layouts. Each Layout in turn will then be responsible for all the components using it.
Child route or nested route will have a new layout and pass it to Dashboard layout as props in addition will work as per expectation.