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:
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:
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);
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;
How you toggle the showSellerLinks
back to false I leave as an exercise for you to resolve for your app's specific use case.