Search code examples
javascriptreactjsnext.jslocalizationchakra-ui

How to add active class to link with current page and locale?


I have a subheader menu where I would like to add an active class to the active page. The problem is when I change the locale. If my link look like: my-site/my-page - it works but if my link: my-site/fr/my-page - doesn’t work. Also, use Storyblok headless CMS.

import { Box, HStack, Link, LinkProps, List, ListItem } from "@chakra-ui/react";
import NextLink from "next/link";
import React from "react";


type SubHeaderLinkProps = {
  name: string;
  href: string;
  isActive: boolean;
};
const activeLinkStyles: LinkProps = {
  color: "orange.400",
  borderBottom: "1px solid",
  borderColor: "orange.400",
};

const inActiveLinkStyles: LinkProps = { color: "white" };
const SubHeaderLink: React.VFC<SubHeaderLinkProps> = ({
  name,
  href,
  isActive,
}) => (
  
  <ListItem _last={{ base: { pr: 8 }, lg: { pr: 0 } }}>
    <NextLink href={href} passHref>
      <Link
        sx={isActive ? activeLinkStyles : inActiveLinkStyles}
        py={5}
        w="min-content"
        d="block"
        whiteSpace="nowrap"
     >
        {href}
      </Link>
    </NextLink>
  </ListItem>
);

Also, Added another code file where I use SubHeaderLink component.

import {
  SubHeaderLink,
  SubHeaderLinks,
} from "@/components/layout/subHeader/SubHeader";
import { ReactStoryblokComponent, StoryblokLink } from "@/types/storyblok";
import { useRouter } from "next/router";
import { useStoryblokLinkParser } from "storyblok/useStoryblokLinkParser";

type Blok = {
  subHeaderLinks: { _uid: string; linkName: string; href: StoryblokLink }[];
};

const StoryblokSubHeader: ReactStoryblokComponent<Blok> = ({
  blok: { subHeaderLinks },
}) => {
  const { asPath } = useRouter();
  const { getHref } = useStoryblokLinkParser();

  return (
    <SubHeaderLinks>
      {subHeaderLinks.map(({ _uid, href, linkName }) => (
        <SubHeaderLink
          key={_uid}
          href={getHref(href)}
          name={linkName}
          isActive={asPath === getHref(href)}
        />
      ))}
    </SubHeaderLinks>
  );
};

export default StoryblokSubHeader;

Solution

  • The asPath property contains the current path without the locale value. From the router object documentation:

    asPath: String - The path (including the query) shown in the browser without the configured basePath or locale.

    Assuming getHref(href) returns a path containing a locale in it, you need to compare it to asPath with the locale as well.

    const StoryblokSubHeader: ReactStoryblokComponent<Blok> = ({ blok: { subHeaderLinks } }) => {
        const { asPath, locale, defaultLocale } = useRouter(); // Get the current locale
        const { getHref } = useStoryblokLinkParser();
    
        const getCurrentPath = () => {
            if (locale === defaultLocale) return asPath
    
            return `/${locale}${asPath}`
        }
    
        return (
            <SubHeaderLinks>
                {subHeaderLinks.map(({ _uid, href, linkName }) => (
                    <SubHeaderLink
                        key={_uid}
                        href={getHref(href)}
                        name={linkName}
                        isActive={getCurrentPath() === getHref(href)}
                    />
                ))}
            </SubHeaderLinks>
        );
    };