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() bees 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 pleted 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 = '/'
ponent = {LandingPage}
/>
<Route exact path = '/register'
ponent = {Register}
/>
<ProtectedRoute exact path = '/Success'
ponent = {Success}
/>
<Route path="*" ponent = {() => "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
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() bees 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 pleted 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 = '/'
ponent = {LandingPage}
/>
<Route exact path = '/register'
ponent = {Register}
/>
<ProtectedRoute exact path = '/Success'
ponent = {Success}
/>
<Route path="*" ponent = {() => "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
Share
Improve this question
asked May 31, 2020 at 6:21
xyz6675xyz6675
3652 gold badges7 silver badges18 bronze badges
4
- You will need to conditionally render the items just like you mentioned in your postscript. – Nafiz Ahmed Commented May 31, 2020 at 6:36
- However, isLoggedIn does not change its value from false to true. It remains false everytime. – xyz6675 Commented May 31, 2020 at 6:39
-
It is because your app ponent does not render with changes to authentication. A react ponent will rerender only if there is a change in its state or props. And your
isAuthenticated
does not satisfy either one of those and thus, the changes in navbar do not get reflected. – Nafiz Ahmed Commented May 31, 2020 at 9:29 - How can I bat that? I need to do it – xyz6675 Commented May 31, 2020 at 19:31
1 Answer
Reset to default 3First, 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 acplish 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
ponent.
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
ponent.
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 ponents 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 ponent 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.