How to hide navbar in login page in react router

Viewed 45832

I want to hide the navbar in a login page.

I did it actually, but I can't see the navbar on other pages.

This code is part of My App.jsx file.

I make history in App's state. And I hide navbar, when this pathname is '/' or '/login'.

It works!

But then I typed the ID and password, and clicked the login button, got 'success' result, and navigated to '/main'.

Now I can't see navbar in main component too.

How can I do this?

Sorry about my short english. If you can't understand my question, you can comment.

constructor(props) {
  super(props);
  this.state = {
    isAlertOpen: false,
    history: createBrowserHistory(),
  };
  this.toggleAlert = this.toggleAlert.bind(this);
}

<BrowserRouter>
  <div className="App">
    {this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
      : <Header toggleAlert={this.toggleAlert} />}
    <div className="container">
      {this.state.history.location.pathname === '/' || this.state.history.location.pathname === '/login' ? null
        : <Navbar />}
      <Route exact path="/" render={() => <Redirect to="/login" />} />
      <Route path="/login" component={Login} />
      <Route path="/main" component={Main} />
      <Route path="/user" component={User} />
      <Route path="/hw-setting" component={Setting} />
      <Route path="/hw-detail/:id" component={HwDetail} />
      <Route path="/gas-detail/:id" component={GasDetail} />
      {this.state.isAlertOpen ? <Alert /> : null}
    </div>
  </div>
</BrowserRouter>

login(event) {
  event.preventDefault();
  userService.login(this.state.id, this.state.password).subscribe(res => {
    if (res.result === 'success') {
      global.token = res.token;
      this.props.history.push('/main');
    } else {
      alert(`[ERROR CODE : ${res.statusCode}] ${res.msg}`);
    }
});
6 Answers

You could structure your Routes differently so that the Login component doesn't have the Header Like

<BrowserRouter>
  <Switch>
  <div className="App">
    <Route exact path="/(login)" component={LoginContainer}/>
    <Route component={DefaultContainer}/>

  </div>
  </Switch>
</BrowserRouter>

const LoginContainer = () => (
  <div className="container">
    <Route exact path="/" render={() => <Redirect to="/login" />} />
    <Route path="/login" component={Login} />
  </div>
)


 const DefaultContainer = () => (
    <div>
    <Header toggleAlert={this.toggleAlert} />
    <div className="container">
      <Navbar />
      <Route path="/main" component={Main} />
      <Route path="/user" component={User} />
      <Route path="/hw-setting" component={Setting} />
      <Route path="/hw-detail/:id" component={HwDetail} />
      <Route path="/gas-detail/:id" component={GasDetail} />
      {this.state.isAlertOpen ? <Alert /> : null}
    </div>
    </div>
 )

Simplest way is use div tag and put components in which you want navbar and put login route component outside div tag:

<div className="App">
  <Router>

    <Switch>
      <Route exact path="/" component={Login} />
      <div>
        <NavBar />
   
        <Route exact path="/addproduct" component={Addproduct}></Route>
        <Route exact path="/products" component={Products}></Route>
     
      </div>

    </Switch>
  </Router>

</div>

As of the latest release of React Router v6, it is no longer possible to pass a <div> component inside the Routes (v6) aka Switch(v5 or lower) to render a Navbar. You will need to do something like this:

  1. Create two Layout components. One simply renders a Nav and the other one does not. Suppose we name them
  • <WithNav />
  • <WithoutNav />
  1. You will need to import <Outlet /> from the React router and render inside the Layout components for the routes to be matched.

Then in your App or where ever you have your Router you will render like below ....


// WithNav.js (Stand-alone Functional Component)
import React from 'react';
import NavBar from 'your navbar location';
import { Outlet } from 'react-router';

export default () => {
  return (
    <>
      <NavBar />
      <Outlet />
    </>
  );
};


// WithoutNav.js (Stand-alone Functional Component)
import React from 'react';
import { Outlet } from 'react-router';

export default () => <Outlet />


// your router (Assuming this resides in your App.js)

      <Routes>
        <Route element={<WithoutNav />}>
          <Route path="/login" element={<LoginPage />} />
        </Route>
        <Route element={<WithNav />}>
          <Route path="/=example" element={<Example />} />
        </Route>
      </Routes>

LoginPage will not have a nav however, Example page will

Put the Route with path="/" below every other routes :

<Switch>
  <Route path="/login" component={Login} />
  <Route path="/" component={Home} />
</Switch>

It will work.

I'm was trying to solve this problem, what i did was add component helmet, to install it use : yarn add react-helmet --save.

import {Helmet} from 'react-helmet';
<Helmet>
   <script src="https://kit.fontawesome.com/.....js" crossorigin="anonymous"></script>
</Helmet>

The accepted answer has problem if you need to add other default route within the switch if no other route matches, e.g., 404 page, not found page.

I ended up using simple css to hide navigation bar inside my login page.

class LoginPage extends React.Component<>{

   ...

   // Hide navigation bar in login page. Do it inside ComponentDidMount as we need to wait for navbar to render before hiding it.
   componentDidMount(){
      document.getElementById('navigation-bar')!.style.display = "none";
   }

   componentWillUnmount(){
      document.getElementById('navigation-bar')!.style.display = "flex";
   }

   render(){
      return(
          // your login/signup component here
          ...
      )
   }

}

Related