When passing the className
props to the child component, sometimes the className
for the active link is not correctly reflected in the DOM element during production:
- The child component (Link) receives the
className
prop for the active link from the parent.
https://i.sstatic.net/qCabN.png
- The child component (Link) in the DOM does not apply the class if the link is active.
https://i.sstatic.net/ijzjL.png
This is how my code looks:
- Navbar
// Navbar.tsx
import classnames from 'classnames';
import { useRouter } from 'next/router';
...
const Navbar = () => {
const router = useRouter();
const navigations = [
{
href: '/',
label: 'Home'
},
{
href: '/profile',
label: 'Profile'
}
];
return (
...
{navigations.map((nav) => (
<NavLink key={nav.label} href={nav.href} isActive={router.asPath === nav.href}>
{nav.label}
</NavLink>
))}
...
);
};
export default Navbar;
- Parent component
// NavLink.tsx
import classnames from 'classnames';
import Link from '@/components/elements/Link';
import styles from '@/components/parts/Navbar/styles.module.scss';
import type { NavLinkProps } from './types';
const NavLink = ({ children, href, isActive }: NavLinkProps) => (
<Link
href={href}
className={classnames(styles.navbar__link, {
[styles.navbar__link_active]: isActive
})}
>
{children}
</Link>
);
export default NavLink;
- Child component
// Link.tsx
import dynamic from 'next/dynamic';
import type { LinkProps } from './types';
const NextLink = dynamic(() => import('next/link'));
const Link = ({ children, href, target, isExternal, className, label, role }: LinkProps) => {
if (isExternal) {
return (
<a
href={href}
target={target ?? '_blank'}
rel="noopener noreferrer"
className={className}
aria-label={label}
role={role}
>
{children}
</a>
);
}
return (
<NextLink href={href}>
<a target={target ?? '_self'} className={className} aria-label={label} role={role}>
{children}
</a>
</NextLink>
);
};
export default Link;