Spencer FengSpencer Feng

Authentication in React Apps with JWT: Part 6

Welcome to the sixth tutorial in our ‘Authentication and Authorisation in React Apps with JSON Web Tokens’ series. So far, our app has been able to handle user signup and user login. But there is no way to tell if a user is logged in or not without checking if there is a JWT in the browser’s localStorage. In this tutorial, we have following tasks, so that the users can tell their login status very easily.

  • Show correct navigation menu items and information in the navigation menu bar

Show correct navigation menu items and information in the navigation menu bar

The first thing we need to do is to hide the ‘Login’ and ‘Signup’ menu items from logged-in users. The navigation menu is managed in the ‘Navbar’ component. In order for the ‘Navbar’ component to be aware of user login status, we need to pass the store state to it.  So, we need to separate the ‘Navbar’ component into a container component which can get the store state and a presentational component which can get the store state as a prop passed from the container component.

Let’s create the container component first. Please create the ‘client/src/components/NavbarContainer.js’ file and put the code below inside it.

import React from 'react';
import { connect } from 'react-redux';
import Navbar from './Navbar';

const mapStateToProps = (state, ownProps) => ({
    cUser: state.cUser
});

export default connect(mapStateToProps, null)(Navbar);

Then we need to go to ‘client/src/App.js’ to replace

import Navbar from './components/Navbar';

with

import Navbar from './components/NavbarContainer';

The existing ‘Navbar.js’ will be used as the presentational component and now it can access the cUser object in the store from the cUser prop. Things are pretty straightforward here now. If the cUser object is empty, it means that there is not a logged-in user and then we need to hide the welcome message and the logout link. Otherwise, it means there is a logged-in user and we need to hide the ‘Login’ and ‘Signup’ menu items and display the welcome message and the logout link.

It looks like we need to check if the cUser object is empty or not in several place, I think it’s better to create a helper function which checks if a function is empty or not.

So let’s create the ‘client/src/helpers.js’ file and put the helper function inside it.

export function isEmpty(obj) {

    for(var key in obj) {
        if(obj.hasOwnProperty(key))
            return false;
    }
    return true;

}

After creating the helper function, we are going to import it to ‘client/src/components/Navbar.js’ and use it to decide when to display and hide some navigation menu items.

Let’s replace the code in ‘client/src/components/Navbar.js’ with the code below:

import React, { Component } from 'react';
import { IsEmpty } from '../helpers';
import { Link } from 'react-router-dom';

class Navbar extends Component {

    render() {

        return (

            <nav className="navbar navbar-inverse navbar-fixed-top">
                <div className="container">
                    <div className="navbar-header">
                        <button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                            <span className="sr-only">Toggle navigation</span>
                            <span className="icon-bar"></span>
                            <span className="icon-bar"></span>
                            <span className="icon-bar"></span>
                        </button>
                        <a className="navbar-brand" href="#">React JWT</a>
                    </div>
                    <div id="navbar" className="collapse navbar-collapse">
                        <ul className="nav navbar-nav">
                            <li className="active"><Link to='/'>Home</Link></li>
                        </ul>
                        <ul className="nav navbar-nav navbar-right">
                            {IsEmpty(this.props.cUser) && 
                                <li><Link to='/login'>Login</Link></li>
                            }
                            {IsEmpty(this.props.cUser) &&
                                <li><Link to='/signup'>Signup</Link></li>
                            }
                            {!IsEmpty(this.props.cUser) &&
                                <li className="dropdown">
                                    <a className="dropdown-toggle" href="#" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
                                        Hello, {this.props.cUser.firstName} {this.props.cUser.lastName} <span className="caret"></span>
                                    </a>
                                    <ul className="dropdown-menu">
                                        <li><a href="#">Logout</a></li>
                                    </ul>
                                </li>
                            }
                        </ul>
                    </div>
                </div>
            </nav>

        )

    }

}

export default Navbar;

The changes include:

  • Import our ‘IsEmpty()’ helper function
  • Wrap the ‘Login’ menu item in a conditional statement and it is only rendered if the cUser object is empty
  • Wrap the ‘Signup’ menu item in a conditional statement and it is only rendered if the cUser object is empty
  • Wrap the welcome message and the logout link in a conditional statement and they are only rendered if the cUser object is empty
  • Display the logged-in user’s first name and last name.

It is great that users can tell their login status very easily now.

Let’s call it a day. In the next tutorial in this series, we will handle the situation where we need to keep the users’ login status after they refresh the page. See you next time.

View the source code for this tutorial on GitHub.

Please sign up to our Newsletter if you want to get notified when new tutorials are available.

×