How to update NavBar component in React upon successful log-in and before logging in

Viewed 9094

I am trying to modify the Navbar contents before and after logging in so that before logging in, it shows Login and Register and after logging in, it shows other tabs apart from those two. I have an Auth.js with a function called isAuthenticated() which returns true if the user is logged in or false otherwise. Initially, isAuthenticated() returns false, so the Navbar shows register and login. However, once the user logs in, isAuthenticated() becomes true but that is not reflected in Navbar. How can I change that to ensure that it shows different things upon login/logout.

PS - I havent completed navigation but I can conditionally render it to show different things if isLoggedin is true or false.

App.js

import ProtectedRoute from './protectedroute'
import Auth from './Auth'

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
     const isAuthenticated = Auth.isAuthenticated() 
     console.log(isAuthenticated)
  return (
      <Router>
        <div>
          <NavigationBar isLoggedin={isAuthenticated}/>
          <Switch>
            <Route exact path = '/'
              component = {LandingPage}
            />
            <Route exact path = '/register'
              component = {Register}
            />
            <ProtectedRoute exact path = '/Success' 
              component = {Success}
            />
            <Route path="*" component = {() => "404 NOT FOUND"}/>
          </Switch>
        </div>
      </Router>
  );
}
}

export default App;

Auth.js

class Auth {
    constructor() {
        this.authenticated = false;
    }

    login() {
        this.authenticated = true;
    }

    logout() {
        this.authenticated = false;
    }

    isAuthenticated() {
        return this.authenticated;
    }
}

export default new Auth();

NavigationBar.js

import React from 'react'
import { Button, Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
import { Link } from 'react-router-dom'


class NavigationBar extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    const isLoggedin = this.props.isLoggedin
    console.log(isLoggedin)
    return (
      <Navbar expand="lg">
        <Navbar.Brand >hello</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="ml-auto">
            <Nav.Link><Link to='/'>Login</Link></Nav.Link>
            <Nav.Link><Link to='/register'>Register</Link></Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
    )
  }
}

export default NavigationBar
1 Answers

First, you will need to render your navbar based on your session. i.e. If there is a change in a session like a user is logged in or logged out, the navbar needs to render.

For simplicity, to accomplish the above task, we will keep the isAuthenticated as an App state property and will pass the isAuthenticated as a prop of NavigationBar. Now any change of isAuthenticated will result in a render of the NavigationBar component.

Code example, in App.js:

constructor(props) {
  super(props);
  this.state = { isAuthenticated: false };
}

render() {
  const { isAuthenticated } = this.state;
  .
  .
  .

instead

const isAuthenticated = Auth.isAuthenticated()

Now, since we removed the Auth.js file and we do require methods like login and logout, we will add such methods in the App component.

Example:

class App extends React.Component {
  constructor(props) {
    super(props);
  }

  login = () => {
    this.setState({ isAuthenticated: true });
  }

  logout = () => {
    this.setState({ isAuthenticated: false });
  }

  render() { ...

And we will need to call these methods depending on the user's activity. Like if a user signs in successfully, we will call the login method. Now, it is important to note that you need to pass these methods as props to child components who will call these. For example, your NavigationBar may need to call the logout and so you pass the method like

<NavigationBar isLoggedin={isAuthenticated} logout={this.logout}/>

Finally, now, based on isLoggedin in NavigationBar, you can render the conditional items.

For example, in NavigationBar.js file,

<Nav className="ml-auto">
  {isLoggedin && (<Nav.Link><Link to='/logout'>Logout</Link></Nav.Link>)}
  {!isLoggedin && (<Nav.Link><Link to='/'>Login</Link></Nav.Link>)}
  {!isLoggedin && (<Nav.Link><Link to='/register'>Register</Link></Nav.Link>)}
</Nav>

The above code will render login and register items if a user is not signed in and vice versa.

Now, all through the walkthrough, we start and maintain the user session in the react component state only. This is not ideal since whenever a user refreshes the page, the session will be lost. To mitigate the issue, you will need to use local storage or any other approach that you may find suitable.

Related