Search code examples
javascriptreactjsreact-routerjsxnavbar

Updating Navbar Links in React on "Become a Seller" Click


I am facing a challenge related to updating navbar links dynamically. I want the navbar to display "Logo," "Seller Home," "About," and "Sell a Product" links when the user clicks on the "Become a Seller" link.

I am using:

"react-router-dom": "^5.2.0",
"react": "^16.13.1"

Issue Description:

  • I want to dynamically update the navbar links based on user actions, specifically when a user clicks on the "Become a Seller" link.
  • After extensive research and trial and error, I haven't been able to find a clear solution or relevant resources that address this specific scenario.

What I've Tried:

I've looked through various tutorials and documentation but couldn't find a clear example or explanation related to updating navbar links dynamically.

What I'm Looking For:

  1. How can I dynamically update the navbar to display only "Logo," "Seller Home," "About," and "Sell a Product" links when the user clicks on "Become a Seller"?
  2. Are there any React concepts or features I should focus on to achieve this particular behavior?

Navbar.js:

import React, { Fragment, useState } from 'react';
import { Link, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout } from '../actions/auth';
import { MdKeyboardArrowDown } from 'react-icons/md';
import { FaCartArrowDown } from 'react-icons/fa';
import { Navbar as BootstrapNavbar, Nav } from 'react-bootstrap';
import './Navbar.css';

const MyNavbar = ({ logout, isAuthenticated }) => {
  const [redirect, setRedirect] = useState(false);

  const logout_user = () => {
    logout();
    setRedirect(true);
  };

  const guestLinks = () => (
    <Fragment>
      <li className='nav-item mr-3'>
        <Link className='nav-link' to='/login'>
          Login
        </Link>
      </li>
      <li className='nav-item mr-3'>
        <Link className='nav-link' to='/sellerhome'>
          Become a Seller
        </Link>
      </li>
    </Fragment>
  );

  const authLinks = () => (
    <li className='nav-item mr-3'>
      <a className='nav-link' href='#!' onClick={logout_user}>
        Logout
      </a>
    </li>
  );

  return (
    <Fragment>
      <BootstrapNavbar expand='lg' bg='light'>
        <Link className='navbar-brand' to='/'>
          Auth System
        </Link>
        <form className='form-inline d-1 d-lg-inline mr-5'>
          <input
            className='form-control mr-sm-1 custom-search-input'
            type='search'
            placeholder='Search'
            aria-label='Search'
          />
        </form>
        <BootstrapNavbar.Toggle aria-controls='navbarNav' />
        <BootstrapNavbar.Collapse id='navbarNav'>
          <Nav className='navbar-nav'>
            <li className='nav-item active mr-3'>
              <Link className='nav-link' to='/'>
                Home <span className='sr-only'>(current)</span>
              </Link>
            </li>

            {/* Add the Cart link */}
            <li className='nav-item mr-3'>
              <Link className='nav-link' to='/cart'>
                More
                <i className='moredown'>
                  <MdKeyboardArrowDown />
                </i>
              </Link>
            </li>
            <li className='nav-item mr-3'>
              <Link className='nav-link' to='/cart'>
                Cart
              </Link>
            </li>
            <li className='nav-item mr-3'>
              <Link className='nav-link' to='/cart'>
                <FaCartArrowDown />
              </Link>
            </li>
            {isAuthenticated ? authLinks() : guestLinks()}
          </Nav>
        </BootstrapNavbar.Collapse>
      </BootstrapNavbar>
      {redirect ? <Redirect to='/' /> : <Fragment></Fragment>}
    </Fragment>
  );
};

// ... (mapStateToProps and export)

const mapStateToProps = (state) => ({
  isAuthenticated: state.auth.isAuthenticated,
});

export default connect(mapStateToProps, { logout })(MyNavbar);

Solution

  • The concept you are looking for is Conditional Rendering.

    Rewrite the code to conditionally render a set of "seller links" versus the normal "nav links", based on some local component state.

    Example:

    import React, { useState } from "react";
    import { Link, useHistory } from "react-router-dom";
    import { useDispatch, useSelector } from 'react-redux';
    import { logout } from '../actions/auth';
    import { MdKeyboardArrowDown } from "react-icons/md";
    import { FaCartArrowDown } from "react-icons/fa";
    import { Navbar as BootstrapNavbar, Nav } from "react-bootstrap";
    
    const MyNavbar = () => {
      const history = useHistory();
      const dispatch = useDispatch();
      const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
    
      const [showSellerLinks, setShowSellerLinks] = useState(false);
    
      const logout_user = () => {
        dispatch(logout());
        history.replace("/");
      };
    
      const guestLinks = (
        <>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/login">
              Login
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link
              className="nav-link"
              to="/sellerhome"
              onClick={setShowSellerLinks.bind(null, true)}
            >
              Become a Seller
            </Link>
          </li>
        </>
      );
    
      const authLinks = (
        <li className="nav-item mr-3">
          <a className="nav-link" href="#!" onClick={logout_user}>
            Logout
          </a>
        </li>
      );
    
      const navLinks = (
        <>
          <li className="nav-item active mr-3">
            <Link className="nav-link" to="/">
              Home <span className="sr-only">(current)</span>
            </Link>
          </li>
          {/* Add the Cart link */}
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/cart">
              More
              <i className="moredown">
                <MdKeyboardArrowDown />
              </i>
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/cart">
              Cart
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/cart">
              <FaCartArrowDown />
            </Link>
          </li>
          {isAuthenticated ? authLinks : guestLinks}
        </>
      );
    
      const sellerLinks = (
        <>
          <li className="nav-item active mr-3">
            <Link className="nav-link" to="/logo">
              Logo
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/sellerhome">
              Seller Home
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/about">
              About
            </Link>
          </li>
          <li className="nav-item mr-3">
            <Link className="nav-link" to="/sell-product">
              Sell a Product
            </Link>
          </li>
        </>
      );
    
      return (
        <BootstrapNavbar expand="lg" bg="light">
          <Link className="navbar-brand" to="/">
            Auth System
          </Link>
          <form className="form-inline d-1 d-lg-inline mr-5">
            <input
              className="form-control mr-sm-1 custom-search-input"
              type="search"
              placeholder="Search"
              aria-label="Search"
            />
          </form>
          <BootstrapNavbar.Toggle aria-controls="navbarNav" />
          <BootstrapNavbar.Collapse id="navbarNav">
            <Nav className="navbar-nav">
              {showSellerLinks ? sellerLinks : navLinks}
            </Nav>
          </BootstrapNavbar.Collapse>
        </BootstrapNavbar>
      );
    };
    
    export default MyNavbar;
    

    Demo

    Edit updating-navbar-links-in-react-on-become-a-seller-click

    enter image description here

    enter image description here

    How you toggle the showSellerLinks back to false I leave as an exercise for you to resolve for your app's specific use case.