skip to Main Content

I need to get the location.pathname and compare it to the links to determine if the clicked anchor/sidebar item should be set to active or not (will become a red button if clicked). The topics should be active first, the user gets there from login page.

The problem is, I cannot get the location pathname of the current page. If I switch to another component of the sidebar, it logs the previous path, which makes it impossible to work with, in my case.

export const SideBar = ({ isSidebarOpen }) => {
  const [IsActive, setIsActive] = useState("topics");
  const location = useLocation().pathname;

  const toggleActiveSideNavbarItem = (id) => {
    console.log(location);
    console.log(id);
    setIsActive(id);
  };

  const anchors = [
    {
      id: "topics",
      icon: <InfoCircleFill />,
      text: "topics",
      link: "",
    },
    {
      id: "employees",
      icon: <PersonLinesFill />,
      text: "employees",
      link: "employees",
    },
    {
      id: "dashboard",
      icon: <BarChartFill />,
      text: "dashboard",
      link: "dashboard",
    },
    {
      id: "user-entry",
      icon: <PersonPlusFill />,
      text: "user",
      link: "user",
    },
  ];

  return (
    <nav>
        {anchors.map((anchor) => (
          <Link
            to={anchor.link}
            key={anchor.id}
            className={`list-group-item border-0 d-inline-block text-truncate mb-3 ${anchor.id === IsActive ? "active" : ""} `}
            onClick={() => toggleActiveSideNavbarItem(anchor.id)}
            data-bs-parent="#sidebar"
          >
            {anchor.icon}
              <span className="ms-2">{anchor.text}</span>
          </Link>
          ))}
      <>
        <Outlet />
      </>
   </nav>
  );
};

Any ideas?

When I use useEffect, the location pathname is fine.

2

Answers


  1. You can manage the className attribute based on location.pathname directly, you don’t really need a state for that.
    You can determine the active one by comparing its link property to the current location.pathname

    export const SideBar = ({ isSidebarOpen }) => {
      const location = useLocation().pathname;
    
      const anchors = [
          // ...
      ];
    
      return (
        <nav>
          {anchors.map((anchor) => (
            <Link
              to={anchor.link}
              key={anchor.id}
              className={`list-group-item border-0 d-inline-block text-truncate mb-3 ${anchor.link === location ? "active" : ""} `}
              data-bs-parent="#sidebar"
            >
              {anchor.icon}
              <span className="ms-2">{anchor.text}</span>
            </Link>
          ))}
        </nav>
      );
    };
    
    Login or Signup to reply.
  2. React-Router-Dom already knows what the active route is, no need to reinvent the wheel. Instead of using the base Link component you should use the NavLink component. It applies an "active" class by default.

    Example:

    import { NavLink, Outlet } from "react-router-dom";
    ...
    
    const anchors = [
      {
        id: "topics",
        icon: <InfoCircleFill />,
        text: "topics",
        link: "/"
      },
      {
        id: "employees",
        icon: <PersonLinesFill />,
        text: "employees",
        link: "employees"
      },
      {
        id: "dashboard",
        icon: <BarChartFill />,
        text: "dashboard",
        link: "dashboard"
      },
      {
        id: "user-entry",
        icon: <PersonPlusFill />,
        text: "user",
        link: "user"
      }
    ];
    
    const SideBar = () => (
      <nav>
        {anchors.map((anchor) => (
          <NavLink
            to={anchor.link}
            key={anchor.id}
            className="list-group-item border-0 d-inline-block text-truncate mb-3"
            data-bs-parent="#sidebar"
            end
          >
            {anchor.icon}
            <span className="ms-2">{anchor.text}</span>
          </NavLink>
        ))}
        <Outlet />
      </nav>
    );
    

    Edit how-to-get-the-current-path-using-react-router-dom

    If you needed to customize the classname though, i.e. "myCustomActiveClassName", then use the callback function syntax. An isActive prop is passed to the callback.

    Example:

    className={({ isActive }) => [
      "list-group-item border-0 d-inline-block text-truncate mb-3",
      isActive ? "myCustomActiveClassName" : null
    ]
      .filter(Boolean)
      .join(" ")
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search