0

I create a navigation that will redirect the page and change the current state of the menu when clicking on the menu.

But I have the problem that when I press the 'back/fordward navigation' button, the menu state doesn't change.

Can someone solve or give directions to fix the above problem.

Photos when running the application

directory structure

Code in app/test/layout.tsx file

"use client";

import Link from "next/link";
import { useState } from "react";

function classNames(...classes: any) {
  return classes.filter(Boolean).join(" ");
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const [navigation, setNavigation] = useState([
    { name: "Home", href: "/test", current: true },
    { name: "Dashboard", href: "/test/dashboard", current: false },
    { name: "Team", href: "/test/team", current: false },
    { name: "Projects", href: "/test/projects", current: false },
    { name: "Calendar", href: "/test/calendar", current: false },
  ]);

  function changeCurrent(item: any) {
    let newNav = [...navigation];
    newNav.map((nav) =>
      nav.name == item.name ? (nav.current = true) : (nav.current = false)
    );
    setNavigation(newNav);
  }

  return (
    <>
      <div className="flex">
        <div className="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
          {navigation.map((item) => (
            <Link
              key={item.name}
              href={item.href}
              className={classNames(
                item.current
                  ? "border-indigo-500 text-gray-900"
                  : "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700",
                "inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
              )}
              aria-current={item.current ? "page" : undefined}
              onClick={() => changeCurrent(item)}
            >
              {item.name}
            </Link>
          ))}
        </div>
      </div>

      <div className="m-8">{children}</div>
    </>
  );
}

I'm dealing with a problem where doing back\forward history on the browser will update the current state of the menu

com0t
  • 3
  • 1

2 Answers2

0

With nextJS, you can use router to get pathname and use it to init current boolean flags based on your url in your navigation state array.

This will allow to have good state when loading page from a direct url (eg. /test/dashboard) or using prev/next button of the web browser.

More information on how to use router here: Get URL pathname in nextjs or https://beta.nextjs.org/docs/api-reference/use-router

Mathieu Guyot
  • 689
  • 5
  • 14
0

@Mathieu I have solved the above problem. But can you tweak my code better?

"use client";

import Link from "next/link";
import { usePathname, useSelectedLayoutSegment } from "next/navigation";
import { useEffect, useState } from "react";

function classNames(...classes: any) {
  return classes.filter(Boolean).join(" ");
}

export default function Nav() {
  const pathname = usePathname();
  const segment = useSelectedLayoutSegment();

  const navigation = [
    {
      name: "Home",
      href: "/test",
      current: pathname === "/test" ? true : false,
    },
    {
      name: "Dashboard",
      href: "/test/dashboard",
      current: pathname === "/test/dashboard" ? true : false,
    },
    {
      name: "Team",
      href: "/test/team",
      current: pathname === "/test/team" ? true : false,
    },
    {
      name: "Projects",
      href: "/test/projects",
      current: pathname === "/test/projects" ? true : false,
    },
    {
      name: "Calendar",
      href: "/test/calendar",
      current: pathname === "/test/calendar" ? true : false,
    },
  ];

  const [navi, setNavigation] = useState(navigation);

  function changeCurrent(item: any) {
    let newNav = [...navigation];
    newNav.map((nav) =>
      nav.name == item.name ? (nav.current = true) : (nav.current = false)
    );
    setNavigation(newNav);
  }

  return (
    <div className="flex">
      <div className="hidden sm:-my-px sm:ml-6 sm:flex sm:space-x-8">
        {navigation.map((item) => (
          <Link
            key={item.name}
            href={item.href}
            className={classNames(
              item.current
                ? "border-indigo-500 text-gray-900"
                : "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700",
              "inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
            )}
            aria-current={item.current ? "page" : undefined}
            onClick={() => {
              changeCurrent(item);
            }}
          >
            {item.name}
          </Link>
        ))}
      </div>
    </div>
  );
}
com0t
  • 3
  • 1
  • I would not put use [navi, setNavigation] as href in link suffice to move to the requested page, thus I could make this component a server component. With this, you could also get rid of changeCurrent code. – Mathieu Guyot Apr 14 '23 at 12:09
  • I still don't fully understand what you are saying. Can you show sample code? Thank you very much – com0t Apr 14 '23 at 15:30