Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

295
Views
React Router v4 with multiple layouts

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.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

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>
over 4 years ago · Santiago Trujillo Report

0

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>;
over 4 years ago · Santiago Trujillo Report

0

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

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!