Using multiple layouts for react-router components

前端 未结 6 1449
执念已碎
执念已碎 2020-12-14 09:22

If I have the following:



  { /* Routes that use layout 1 */ }
  

        
相关标签:
6条回答
  • 2020-12-14 09:38

    You can use routes without a path to define containers that are not defined by the url:

    <Route path="/" component={Containers.App}>
    
      { /* Routes that use layout 1 */ }
      <Route component={Containers.Layout1}>
        <IndexRoute component={Containers.Home}/>
        <Route path="about" component={Containers.About}/>
        <Route path="faq" component={Containers.Faq}/>
        <Route path="etc" component={Containers.Etc}/>
      </Route>
    
      <Route component={Containers.Layout2}>
        { /* Routes that use layout 2 */ }
        <Route path="products" component={Containers.Products}/>
        <Route path="gallery" component={Containers.Gallery}/>
      </Route>
    </Route>
    

    The layout components can then import additional components such as the top nav

    0 讨论(0)
  • 2020-12-14 09:46

    You could create a function RouteWithLayout that renders the <Route> wrapped within the layout:

    const RouteWithLayout = ({ component: Component, layout: Layout, ...rest }) => (
      <Route {...rest} render={props => (
        <Layout>
          <Component {...props} />
        </Layout>
      )} />
    )
    
    const MainLayout = props => (
      <div>
        <h1>Main</h1>
        {props.children}
      </div>
    )
    
    const AltLayout = props => (
      <div>
        <h1>Alt</h1>
        {props.children}
      </div>
    )
    
    const Foo = () => (
      <p>Foo</p>
    )
    
    const Bar = () => (
      <p>Bar</p>
    )
    
    const App = () => (
      <div>
        <Switch>
          <RouteWithLayout exact path="/foo" layout={MainLayout} component={Foo} />
          <RouteWithLayout exact path="/bar" layout={AltLayout} component={Bar} />
        </Switch>
      </div>
    )
    
    0 讨论(0)
  • 2020-12-14 09:48

    Pintouch, I was able to get this working with the following example:

    Layout1:

    import React from 'react'
    
    const Layout1 = (props) => (
        <div>
            <h1>Layout 1</h1>
            {props.children}
        </div>
    )
    
    export default Layout1
    

    Layout2:

    import React from 'react'
    
    const Layout2 = (props) => (
        <div>
            <h1>Layout 2</h1>
            {props.children}
        </div>
    )
    
    export default Layout2
    

    Layout Container:

    import React from 'react'
    
    const LayoutContainer = (props) => (
        <div>
                    {props.children}
        </div>
    )
    
    export default LayoutContainer
    

    Routes:

    import React from 'react';
    import { Router, Route, IndexRoute, hashHistory } from 'react-router';
    
    import LayoutContainer from './LayoutContainer'
    import Layout1 from './Layout1'
    import Layout2 from './Layout2'
    import ContactManagerView from './ContactManagerView'
    import CallerIdView from './CallerIdView'
    import NotFound from './NotFound'
    
    <Router history={hashHistory}>
        <Route path="/" component={LayoutContainer}>
            <Route component={Layout1}>
                <IndexRoute component={DashboardView}/>
                <Route path='Contacts' component={ContactManagerView}/>
            </Route>
    
            <Route component={Layout2}>
                <Route path='CallerId' component={CallerIdView}/>
            </Route>
    
            <Route component={Layout}>
                <Route path='*' component={NotFound}/>
            </Route>
        </Route>
    </Router>
    
    0 讨论(0)
  • 2020-12-14 09:57

    I came across this question and found a solution that I want to share.

    With react router v4 we could render the routes directly in your layout. Which is more readable and easy to maintain.

    Layout

    export class MainLayout extends React.PureComponent {
      render() {
        return (
          <div>
            <Header />
            {this.props.children}
            <Footer />
          </div>
        );
      }
    }
    
    Mainlayout.propTypes = {
      children: PropTypes.node.isRequired,
    }
    

    Router

    export default function App() {
      return (
        <Switch>
          <MainLayout>
            <Switch>
              <Route path="/" component={Home} />
              <Route path="/about" component={About} />
            </Switch>
          </MainLayout>
          <OtherLayout>
            .... other paths
          </OtherLayout>
        </Switch>
      );
    }
    
    0 讨论(0)
  • 2020-12-14 10:00

    Route's path property has accepted an array of strings for a while now. See https://github.com/ReactTraining/react-router/pull/5889/commits/4b79b968389a5bda6141ac83c7118fba9c25ff05

    Simplified to match the question routes, but I have working multiple layouts essentially like this (using react-router 5):

    <App>
      <Switch>
        <Route path={["/products", "/gallery"]}>
          <LayoutTwo>
            <Switch>
              <Route path="/products" component={Products} />
              <Route path="/gallery" component={Gallery} />
            </Switch>
          </LayoutTwo>
        </Route>
        {/* Layout 1 is last because it is used for the root "/" and will be greedy */}
        <Route path={["/about", "/faq", "/etc", "/"]}>
          <LayoutOne>
            <Switch>
              <IndexRoute component={Home} />
              <Route path="/about" component={About} />
              <Route path="/faq" component={Faq} />
              <Route path="/etc" component={Etc} />
            </Switch>
          </LayoutOne>
        </Route>
      </Switch>
    </App>
    

    This solution prevents re-mounting the layouts on route changes, which can break transitions, etc.

    0 讨论(0)
  • 2020-12-14 10:03

    Here's a great way to use multiple layouts with different React components.

    In your router you can use:

    <Router history={browserHistory}>
      <Route component={MainLayout}>
        <Route path="/" component={Home} />
        <Route path="/about" component={About} />
      </Route>
      <Route component={EmptyLayout}>
        <Route path="/sign-in" component={SignIn} />
      </Route>
      <Route path="*" component={NotFound}/>
    </Router>
    

    Source: https://sergiotapia.me/different-layouts-with-react-router-71c553dbe01d

    0 讨论(0)
提交回复
热议问题