skip to Main Content

I’m working on a ReactJS website styled with Tailwind CSS, and I have a navigation bar and footer in separate components. The navigation bar consists of three menu items: Home, About, and Contact. By default, the Home menu item is red, and the About and Contact items are black to indicate we’re on the Home page.

Page load default

When the "Contact" menu item is clicked, it turns red, and Home and About become black, and the "Contact" content loads which indicates that we’re on the Contact page.

When contact is clicked

Now, I have a link named "culture" in the footer under the "Company" section. Clicking on "culture" should navigate to the culture page showing its own content. However, I also want it to change the active menu item in the navigation bar to "About" to indicate the relationship between "culture" and "About."

I’m looking for a way to achieve this functionality. Specifically, I’d like to know how to update the active menu item in the navigation bar when clicking on "culture" in the footer, while ensuring that "culture" still opens its own page.

Right now , the problem is if i am in Contact and i click on culture in the footer, it loads the culture page but the nav indicator still remains in Contact

enter image description here

Any help or code example to implement this would be greatly appreciated!

this is my Navbar.jsx:

import React, {useState} from "react";
import {Link} from "react-router-dom";

const NavBar = () => {
  const [activeItem, setActiveItem] = useState("Home");

  const handleItemClick = (item) => {
    setActiveItem(item);
  };
  return (
    <nav className="bg-green-100 px-8 py-8 sm:pt-6 sm:pb-4 pb-5 mx-auto max-w-screen-xl lg:px-12 lg:py-12">
      <div>
        <ul className="flex space-x-12 justify-center">
          <li>
            <Link
              to="/"
              onClick={() => handleItemClick("Home")}
              className={`text-black ${
                activeItem === "Home" && "font-bold text-red-600"
              }`}>
              Home
            </Link>
          </li>
          <li>
            <Link
              to="/about"
              onClick={() => handleItemClick("About")}
              className={`text-black ${
                activeItem === "About" && "font-bold text-red-600"
              }`}>
              About
            </Link>
          </li>
          <li>
            <Link
              onClick={() => handleItemClick("Contact")}
              to="/contact"
              className={`text-black ${
                activeItem === "Contact" && "font-bold text-red-600"
              }`}>
              Contact
            </Link>
          </li>
        </ul>
      </div>
    </nav>
  );
};

export default NavBar;

this is my footer.jsx:

import React from "react";
import {Link} from "react-router-dom";

const Footer = () => {
  return (
    <footer className="bg-gray-200 px-4 py-4 sm:pt-6 sm:pb-4 pb-5 mx-auto max-w-screen-xl lg:px-8 lg:py-6">
      <div className="flex justify-between">
        <div>
          <h3 className="font-semibold text-gray-700">Company</h3>
          <ul className="flex space-x-4">
            <li>
              <Link to="/culture" className="text-gray-500">
                Culture
              </Link>
            </li>
          </ul>
        </div>
      </div>
    </footer>
  );
};

export default Footer;

this is my App.jsx:

import React from "react";
import {BrowserRouter, Route, Routes} from "react-router-dom";
import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
import Home from "./page/Home";
import About from "./page/About";
import Culture from "./page/Culture";
import Contact from "./page/Contact";

const App = () => {
  return (
    <BrowserRouter>
      <Navbar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="/culture" element={<Culture />} />
      </Routes>
      <Footer />
    </BrowserRouter>
  );
};

export default App;

2

Answers


  1. You can do that by using the useLocation hook:

    For example:

     const location = useLocation()
     const [activeItem, setActiveItem] = useState("Home");
    
     const sidebarActive = [
        {
          title: 'Home',
          route: '/home'
        },
        {
          title: 'contact',
          route: '/contact'
        },
        {
          title: 'About',
          route: '/about'
        },
        {
          title: 'About',
          route: '/culture'
        }
      ]
      
    useEffect(() => {
        const headerText = sidebarActive.find((item) =>
          item.route.includes(location.pathname.split('/')[1])
        )
        console.log('in useEffect called', location.pathname, headerText)
        setActiveItem(headerText?.title)
      }, [location])
    Login or Signup to reply.
  2. Instead of using the plain Link component and local state to set what link is "active" you should instead import and use the NavLink component that does this for you. Use the NavLink‘s callback version of the className prop to access that link’s isActive prop and conditionally apply the appropriate active CSS classname.

    Example:

    NavBar

    import React, { useState } from "react";
    import { NavLink } from "react-router-dom";
    
    const NavBar = () => {
      return (
        <nav className="bg-green-100 px-8 py-8 sm:pt-6 sm:pb-4 pb-5 mx-auto max-w-screen-xl lg:px-12 lg:py-12">
          <div>
            <ul className="flex space-x-12 justify-center">
              <li>
                <NavLink
                  to="/"
                  end
                  className={({ isActive }) => 
                    [
                      "text-black",
                      isActive ? "font-bold text-red-600" : null
                    ].filter(Boolean).join(" ")
                  }
                >
                  Home
                </NavLink>
              </li>
              <li>
                <NavLink
                  to="/about"
                  className={({ isActive }) => 
                    [
                      "text-black",
                      isActive ? "font-bold text-red-600" : null
                    ].filter(Boolean).join(" ")
                  }
                >
                  About
                </NavLink>
              </li>
              <li>
                <NavLink
                  to="/contact"
                  className={({ isActive }) => 
                    [
                      "text-black",
                      isActive ? "font-bold text-red-600" : null
                    ].filter(Boolean).join(" ")
                  }
                >
                  Contact
                </NavLink>
              </li>
            </ul>
          </div>
        </nav>
      );
    };
    
    export default NavBar;
    

    Footer

    import React from "react";
    import { NavLink } from "react-router-dom";
    
    const Footer = () => {
      return (
        <footer className="bg-gray-200 px-4 py-4 sm:pt-6 sm:pb-4 pb-5 mx-auto max-w-screen-xl lg:px-8 lg:py-6">
          <div className="flex justify-between">
            <div>
              <h3 className="font-semibold text-gray-700">Company</h3>
              <ul className="flex space-x-4">
                <li>
                  <NavLink
                    to="/culture"
                    className={({ isActive }) => 
                      [
                        "text-gray-500",
                        isActive ? "font-bold text-red-600" : null
                      ].filter(Boolean).join(" ")
                    }
                  >
                    Culture
                  </NavLink>
                </li>
              </ul>
            </div>
          </div>
        </footer>
      );
    };
    
    export default Footer;
    

    If you’d like a "relationship" between the "about" page and the "culture" page then I’d suggest reorganizing the routes so the culture page is a sub-route of "/about".

    Example:

    const App = () => {
      return (
        <BrowserRouter>
          <Navbar />
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about">
              <Route index element={<About />} />
              <Route path="culture" element={<Culture />} />
            </Route>
            <Route path="/contact" element={<Contact />} />
          </Routes>
          <Footer />
        </BrowserRouter>
      );
    };
    

    The footer will then link to "/about/culture" and both the "about" link in the navbar and "culture" link in the footer will be active.

    const Footer = () => {
      return (
        <footer className="bg-gray-200 px-4 py-4 sm:pt-6 sm:pb-4 pb-5 mx-auto max-w-screen-xl lg:px-8 lg:py-6">
          <div className="flex justify-between">
            <div>
              <h3 className="font-semibold text-gray-700">Company</h3>
              <ul className="flex space-x-4">
                <li>
                  <NavLink
                    to="/about/culture" // <--
                    className={({ isActive }) => 
                      [
                        "text-gray-500",
                        isActive ? "font-bold text-red-600" : null
                      ].filter(Boolean).join(" ")
                    }
                  >
                    Culture
                  </NavLink>
                </li>
              </ul>
            </div>
          </div>
        </footer>
      );
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search