Next.js Discord

Discord Forum

How to route isActive on multiple elements in NextJS

Unanswered
Reddish carpenter ant posted this in #help-forum
Open in Discord
Reddish carpenter antOP
Assuming this is the JSON
{
    url: "",
},
{
   url: "pages",
}.
{
  url: "settings"
}


And we get these urls:
http://localhost:3000/dashboard/sites/327
http://localhost:3000/dashboard/sites/327/pages
http://localhost:3000/dashboard/sites/327/settings/posts

How would you make it so what is after the 'id' will be set to active, so id/[active] if one of the url above matches

Bare in mind, the 'settings/posts the posts is a folder in nextjs.

6 Replies

Reddish carpenter antOP
I got this but this is so bad:
import { dataSiteHeader } from "../../data-site-header";
import SiteHeaderNavigationItem from "./SiteHeaderNavigationItem";
import { useParams, usePathname } from "next/navigation";

function SiteHeaderNavigationList() {
  const { id } = useParams();
  const pathname = usePathname()

  return (
    <nav className="flex w-full h-full bg-[#0e0f10] gap-2">
      {dataSiteHeader && dataSiteHeader.map(item => {
        const isActive = pathname.split('/')[4] === item.url || item.url === "" && pathname.split('/')[4] === undefined
        return <SiteHeaderNavigationItem item={item} isActive={isActive} siteID={id} key={item.id} />
      })}
    </nav>
  )
}

export default SiteHeaderNavigationList;
Somali
 

import { dataSiteHeader } from "../../data-site-header";
import SiteHeaderNavigationItem from "./SiteHeaderNavigationItem";
import { useParams, usePathname } from "next/navigation";

function SiteHeaderNavigationList() {
  const { id } = useParams();
  const pathname = usePathname();
  
  // Extract the relevant URL segment after 'id'
  const segmentAfterId = pathname.split('/')[4] || null;

  return (
    <nav className="flex w-full h-full bg-[#0e0f10] gap-2">
      {dataSiteHeader && dataSiteHeader.map(item => {
        // Check if the segment matches the item URL or if it's the root URL
        const isActive = segmentAfterId 
                         ? segmentAfterId === item.url 
                         : item.url === "";

        return (
          <SiteHeaderNavigationItem 
            item={item} 
            isActive={isActive} 
            siteID={id} 
            key={item.id} 
          />
        );
      })}
    </nav>
  );
}

export default SiteHeaderNavigationList;
I’d be careful when hardcoding the index like you’re doing. This approach is guaranteed to break if you ever change your URL structure.
Somali
Idk try this

import { dataSiteHeader } from "../../data-site-header";
import SiteHeaderNavigationItem from "./SiteHeaderNavigationItem";
import { useParams, usePathname } from "next/navigation";

function getSegmentAfterId(pathname, id) {
    const decodedPath = decodeURIComponent(pathname);
    const segments = decodedPath.split('/');
    const idPosition = segments.indexOf(String(id));
    
    // Return null if id is not found or is the last segment
    if (idPosition === -1 || idPosition === segments.length - 1) {
        return null;
    }

    return segments[idPosition + 1];
}

function SiteHeaderNavigationList() {
  const { id } = useParams();
  const pathname = usePathname();

  if (!dataSiteHeader || !Array.isArray(dataSiteHeader)) {
    return null;  // consider adding some fallback UI or error message
  }

  const segmentAfterId = getSegmentAfterId(pathname, id);

  return (
    <nav className="flex w-full h-full bg-[#0e0f10] gap-2">
      {dataSiteHeader.map(item => {
        const isActive = item.url === segmentAfterId || (!segmentAfterId && item.url === "");
        return (
          <SiteHeaderNavigationItem 
            item={item} 
            isActive={isActive} 
            siteID={id} 
            key={item.id} 
          />
        );
      })}
    </nav>
  );
}

export default SiteHeaderNavigationList;
@Somali Idk try this import { dataSiteHeader } from "../../data-site-header"; import SiteHeaderNavigationItem from "./SiteHeaderNavigationItem"; import { useParams, usePathname } from "next/navigation"; function getSegmentAfterId(pathname, id) { const decodedPath = decodeURIComponent(pathname); const segments = decodedPath.split('/'); const idPosition = segments.indexOf(String(id)); // Return null if id is not found or is the last segment if (idPosition === -1 || idPosition === segments.length - 1) { return null; } return segments[idPosition + 1]; } function SiteHeaderNavigationList() { const { id } = useParams(); const pathname = usePathname(); if (!dataSiteHeader || !Array.isArray(dataSiteHeader)) { return null; // consider adding some fallback UI or error message } const segmentAfterId = getSegmentAfterId(pathname, id); return ( <nav className="flex w-full h-full bg-[#0e0f10] gap-2"> {dataSiteHeader.map(item => { const isActive = item.url === segmentAfterId || (!segmentAfterId && item.url === ""); return ( <SiteHeaderNavigationItem item={item} isActive={isActive} siteID={id} key={item.id} /> ); })} </nav> ); } export default SiteHeaderNavigationList;
Reddish carpenter antOP
Thanks, going have to digest the decode url path not that familiar with it, but it works for 90% will check it once I'm a bit more awake, now bit sleepy 😄

Yeah and I agree with you, I though there was some native nextjs function or something.

Feels like some things are easier in react and some in nextjs, but I think overall nextjs seems better just need to learn the ropes and get faimilar with it
Somali
Check this article out. I’m on my phone but this might work as a good enough guide for now

https://medium.com/@r.gausai/simplify-your-next-js-apps-active-links-with-useactiverouter-and-link-14f428fccf1f