Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render different Layouts using React?

I want to show Navbar only for this url: /contact, /services. And I don't want to show Navbar for /signin. For this moment this is what I have:

import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';

import PublicLayout from './components/layouts/PublicLayout';
import SigninLayout from './components/layouts/SigninLayout';

import Main from './components/pages/Main';
import Services from './components/pages/Services';
import Contact from './components/pages/Contact';

class App extends Component {
    render() {
        return (
            <BrowserRouter>
                <div className="App">
                  <Switch>                    
                    <PublicLayout>
                            <Route exact path='/' component={Main} />
                            <Route exact path='/services' component={Services} />
                            <Route exact path='/contact' component={Contact} />
                    </PublicLayout>
                    <SigninLayout>
                            <Route exact path='/signin' component={Signin} />
                    </SigninLayout>
                  </Switch>
                </div>
            </BrowserRouter>
        );
    }
}

export default App;

When I go to /signin url it still gives me Navbar. So guys - how do you render different layouts for different pages in React? Please help!

UPD: My PublicLayout Code:

import React, { Component } from 'react';
import Navbar from '../nav/Navbar';

class PublicLayout extends Component {
    state = {
        items: [
            { id: 1, name: 'Услуги', link: '/services' },
            { id: 2, name: 'Как это работает?', link: '/contacts' },
            { id: 3, name: 'Войти', link: '/signin' },
        ]
    }

    render() {
        return (
            <div>
                <Navbar items={ this.state.items } />
                { this.props.children }
            </div>
        );
    }
}

export default PublicLayout;

My SignInLayout code:

import React, { Component } from 'react';

class SigninLayout extends Component {
    state = {

    }

    render() {
        return (
            <div>
                { this.props.children }
            </div>
        );
    }
}

export default SigninLayout;

My SignIn component:

import React, { Component } from 'react';

class Signin extends Component {
    state = {

    }

    render() {
        return (
            <div>
                <h1>Войти</h1>
                <form>
                    <input type="text" placeholder="укажите e-mail" />
                    <input type="text" placeholder="укажите пароль" />
                    <button>Войти</button>
                </form>
            </div>
        );
    }
}

export default Signin;
like image 259
Nastro Avatar asked Sep 24 '18 13:09

Nastro


1 Answers

You can achieve this by first choosing which layout to render using your switch statement, and then moving the routing for components that should be rendered inside that layout to inside the layout component.

As a very basic example, your App component could have:

<BrowserRouter>
  <div className="App">
    <Switch>
      <Route path="/signin" component={PrivateLayout} />
      <Route path="/" component={PublicLayout} />
    </Switch>
  </div>
</BrowserRouter>

Now inside PublicLayout, you can render the Nav and also create some new routes e.g.

class PublicLayout extends Component {
  render() {
    return (
      <div>
        <h1>Public Place</h1>
        <Navbar items={[]} />
        <Switch>
          <Route exact path='/' component={Main} />
          <Route exact path='/services' component={Services} />
          <Route exact path='/contact' component={Contact} />
        </Switch>
      </div>
    );
  }
}

export default PublicLayout;

...and in PrivateLayout you can render a set of routes without the NavBar e.g.

class PrivateLayout extends Component {
  render() {
    return (
      <div>
        <h1>Private Place</h1>
        <Switch>
          <Route exact path="/signin" component={Signin} />
          <Route exact path="/signin/otherpath" component={OtherPrivateComponent} />
        </Switch>
      </div>
    );
  }
}

export default PrivateLayout;

Here it is all in one file, which you can also see on this codesandbox:

import React, { Component } from "react";
import ReactDOM from "react-dom";

import { BrowserRouter, Route, Switch } from "react-router-dom";

const NavBar = props => <div>Nav Bar</div>;

class PrivateLayout extends Component {
  render() {
    return (
      <div>
        <h1>Private</h1>
        <Switch>
          <Route exact path="/signin" render={() => <h2>Signin</h2>} />
          <Route
            exact
            path="/signin/otherpath"
            render={() => <h2>Signin Other</h2>}
          />
        </Switch>
      </div>
    );
  }
}

class PublicLayout extends Component {
  render() {
    return (
      <div>
        <h1>Public Place</h1>
        <NavBar />
        <Switch>
          <Route exact path="/" render={() => <h2>Main Page</h2>} />
        </Switch>
      </div>
    );
  }
}

function App() {
  return (
    <div className="App">
      <BrowserRouter>
        <Switch>
          <Route path="/signin" component={PrivateLayout} />
          <Route path="/" component={PublicLayout} />
        </Switch>
      </BrowserRouter>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
like image 117
Tom Avatar answered Oct 11 '22 15:10

Tom