React Router v4 with multiple layouts React Router v4 with multiple layouts reactjs reactjs

React Router v4 with multiple layouts


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>;


2019+

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