import Link from './Link'; // our version of link
export default () => (
  <header className="Header">
    <nav>
      <Link activeClassName="active" href="/">
        <a className="some-other-class">Home</a>
      </Link>
      <Link activeClassName="active" href="/about">
        <a>About</a>
      </Link>
      <Link activeClassName="active" href="/contact">
        <a>Contact</a>
      </Link>
    </nav>
  </header>
);- 
      
- 
        Save remy/0dde38897d6d660f0b63867c2344fb59 to your computer and use it in GitHub Desktop. 
| import { withRouter } from 'next/router'; | |
| import Link from 'next/link'; | |
| import React, { Children } from 'react'; | |
| const ActiveLink = ({ router, children, ...props }) => { | |
| const child = Children.only(children); | |
| let className = child.props.className || ''; | |
| if (router.pathname === props.href && props.activeClassName) { | |
| className = `${className} ${props.activeClassName}`.trim(); | |
| } | |
| delete props.activeClassName; | |
| return <Link {...props}>{React.cloneElement(child, { className })}</Link>; | |
| }; | |
| export default withRouter(ActiveLink); | 
In case someone only needs to match the first url segment, try this:
const ActiveLink = withRouter(({ router, children, ...props }) => (
  <Link {...props}>
    {React.cloneElement(Children.only(children), {
      className:
        `/${router.pathname.split("/")[1]}` === props.href ? `active` : null
    })}
  </Link>
));In case someone using as in links, just change pathname with asPath.
zeti/next already have the use case with withRouter HOC.
https://github.com/zeit/next.js/tree/canary/examples/using-with-router
Thanks a lot! Cleaned version of ActiveLink.
import { withRouter } from 'next/router';
import cx from 'classnames';
import Link from 'next/link';
import React, { Children } from 'react';
const ActiveLink = ({
  router,
  children,
  href,
  activeClassName,
  ...otherProps
}) => {
  const child = Children.only(children);
  const className = cx(child.props.className, {
    [activeClassName]: router.pathname === href && activeClassName
  });
  return (
    <Link href={href} {...otherProps}>
      {React.cloneElement(child, { className })}
    </Link>
  );
};What's that 'classnames' on second line? @emil-alexandrescu
Thank you! Here is my typescript version:
import cx from 'classnames';
import { WithRouterProps } from 'next/dist/client/with-router';
import NextLink from 'next/link';
import { withRouter } from 'next/router';
import { ReactElementLike } from 'prop-types';
import { Children, cloneElement, Component } from 'react';
interface LinkProps extends WithRouterProps {
  href: string;
  children: ReactElementLike;
  activeClassName: string;
}
class Link<P extends LinkProps> extends Component<P> {
  public render() {
    const {
      router,
      children,
      href,
      activeClassName,
      ...otherProps
    } = this.props;
    const child = Children.only(children);
    const active = this.props.router.pathname === href && activeClassName;
    const className = cx(
      child.props.className,
      { [activeClassName]: active }
    );
    return (
      <NextLink href={this.props.href} {...otherProps}>
        {cloneElement(child, { className })}
      </NextLink>
    );
  }
}
export default withRouter(Link);Here's a version using a Hook instead of a HOC.
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
const ActiveLink = ({ children, ...props }) => {
  const router = useRouter();
  const child = React.Children.only(children);
  let className = child.props.className || "";
  if (router.pathname === props.href && props.activeClassName) {
    className = `${className} ${props.activeClassName}`.trim();
  }
  delete props.activeClassName;
  return <Link {...props}>{React.cloneElement(child, { className })}</Link>;
};Here's a version using a Hook and styled-components:
const ActiveLink = ({ children, ...props }) => {
  const router = useRouter()
  const child = React.Children.only(children)
  return (
    <Link {...props}>
      {React.cloneElement(child, { active: router.pathname === props.href })}
    </Link>
  )
}Using example:
<ActiveLink href="/path" prefetch>
  <NavLink>Vikup auto</NavLink>
</ActiveLink>NavLink components something like this:
const NavLink = styled.a`
  color: ${({ active }) => active ? 'red' : 'black'}; 
`Hey guys im having an issue with dynamic routing and this component.
I have a Nav component in components folder:
import Link from './Link';
export default () => (
 <nav>
   <style jsx>{`
     .active {
       color: red;
     }
     .nav-link {
       text-decoration: none;
       padding: 10px;
       display: block;
     }
   `}</style>
   <ul>
     <li>
       <Link activeClassName="active" href="/">
         <a className="nav-link home-link">Home</a>
       </Link>
     </li>
     <li>
       <Link activeClassName="active" href="/about">
         <a className="nav-link">About</a>
       </Link>
     </li>
     <li>
       <Link activeClassName="active" href="/post/[id]" as="/post/first">
         <a>First Post</a>
       </Link>
     </li>
     <li>
       <Link activeClassName="active" href="/post/[id]" as="/post/second">
         <a>Second Post</a>
       </Link>
     </li>
   </ul>
 </nav>
);
and my pages folder look like this:
pages/ |---- post/ | ---- [id]/ | ---- index.js |---- about.js |---- index.js
and the Index.js from [id] folder:
import {useRouter} from 'next/router';
import Nav from '../../../components/Nav';
const Post = () => {
  const router = useRouter();
  const {id} = router.query;
  return (
    <React.Fragment>
      <Nav />
      <h1>Post: {id}</h1>
    </React.Fragment>
  );
};
export default Post;
the problem it's that adds right the active class in al cases except if u reload in /post/[id], if so its return this error and don't add the active class:
Warning: Prop className did not match. Server: "jsx-382284644" Client: "jsx-382284644 active"
in my Link component im comparin the asPath insted of href like this:
import {withRouter} from 'next/router';
import Link from 'next/link';
import React, {Children} from 'react';
const ActiveLink = ({router, children, as, ...props}) => {
  const child = Children.only(children);
  let className = child.props.className || null;
  if (as) {
    if (router.asPath === as && props.activeClassName) {
      className = `${className !== null ? className : ''} ${props.activeClassName}`.trim();
    }
  } else {
    if (router.pathname === props.href && props.activeClassName) {
      className = `${className !== null ? className : ''} ${props.activeClassName}`.trim();
    }
  }
  delete props.activeClassName;
  return (
    <Link as={as} {...props}>
      {React.cloneElement(child, {className})}
    </Link>
  );
};
export default withRouter(ActiveLink);
A version with ES6 destructuring, proptypes and useRotuer hook:
import React from 'react';
import Link from 'next/link';
import PropTypes from 'prop-types';
import { useRouter } from 'next/router';
const ActiveLink = ({ href, activeClassName, children }) => {
  const router = useRouter();
  const child = React.Children.only(children);
  let className = child.props.className || '';
  if (router.pathname === href && activeClassName) {
    className = `${className} ${activeClassName}`.trim();
  }
  return <Link href={href}>{React.cloneElement(child, { className })}</Link>;
};
ActiveLink.propTypes = {
  href: PropTypes.string,
  activeClassName: PropTypes.string,
  children: PropTypes.node.isRequired
};
ActiveLink.defaultProps = {
  href: '',
  activeClassName: ''
};
export default ActiveLink;I do it like this:
const ActiveLink: NextPage<Props> = ({ children, href }) => {
  const router = useRouter();
  return (
    <Link href={href} passHref>
      <Anchor active={router.pathname === href}>{children}</Anchor>
    </Link>
  );
};
const Anchor = styled.a<{ active: boolean }>`
  color: ${props => (props.active ? 'red' : 'blue')};
`;If full control is needed just replace Link all together, from their docs:
import { useRouter } from 'next/router'
function ActiveLink({ children, href }) {
  const router = useRouter()
  const style = {
    marginRight: 10,
    color: router.pathname === href ? 'red' : 'black',
  }
  const handleClick = e => {
    e.preventDefault()
    router.push(href)
  }
  return (
    <a href={href} onClick={handleClick} style={style}>
      {children}
    </a>
  )
}
export default ActiveLinknew typescript version:
import { withRouter } from 'next/router';
const ActiveLink = ({ router, href, children }: any) => {
    (function prefetchPages() {
        if (typeof window !== 'undefined') {
            router.prefetch(router.pathname);
        }
    })();
    const handleClick = (event: React.MouseEvent<HTMLElement>) => {
        event.preventDefault();
        router.push(href);
  
    };
    const isCurrentPath = router.pathname === href || router.asPath === href;
    return (
        <a
            href={href}
            onClick={handleClick}
            className="url-item"
            style={{
                fontWeight: isCurrentPath ? 'bold' : 'normal',
                color: isCurrentPath ? '#F00' : '#fff'
            }}
        >
            {children}
        </a>
    );
};
export default withRouter(ActiveLink);I did something like this with typescript and tailwind css :
import { useRouter } from 'next/router'
import Link from 'next/link'
type Props = {
  href: string
  linkName: string
  activeClassName?: string
} & typeof defaultProps
const defaultProps = {
  activeClassName: 'text-green font-600',
}
export const NavLink = ({ href, linkName, activeClassName }: Props) => {
  const router = useRouter()
  return (
    <Link href={href}>
      <a className={router.pathname === href ? activeClassName : null}>
        {linkName}
      </a>
    </Link>
  )
}
NavLink.defaultProps = defaultProps
If you need support for dynamic routes ([slug], [id], [...param], [[...slug]], etc.) in Next.js. The following will check if the href contains a dynamic route and then check if the "router.asPath" is equal to the "props.as". When matched the "activeClassName" will be added to the link.
Thanks @remy!
import { useRouter } from "next/router";
import Link from "next/link";
import React, { Children } from "react";
const ActiveLink = ({ children, ...props }) => {
  const router = useRouter();
  const child = Children.only(children);
  let className = child.props.className || "";
  const isDynamicRoute = props.href.match(/^\/?\[{1,2}\.{0,3}[a-z]+\]{1,2}$/);
  if (
    router.pathname === props.href &&
    !isDynamicRoute &&
    props.activeClassName
  ) {
    className = `${className} ${props.activeClassName}`.trim();
  } else if (router.asPath === props.as && isDynamicRoute) {
    className = `${className} ${props.activeClassName}`.trim();
  }
  delete props.activeClassName;
  return <Link {...props}>{React.cloneElement(child, { className })}</Link>;
};
export default ActiveLink;A version with ES6 destructuring, proptypes and useRotuer hook:
import React from 'react'; import Link from 'next/link'; import PropTypes from 'prop-types'; import { useRouter } from 'next/router'; const ActiveLink = ({ href, activeClassName, children }) => { const router = useRouter(); const child = React.Children.only(children); let className = child.props.className || ''; if (router.pathname === href && activeClassName) { className = `${className} ${activeClassName}`.trim(); } return <Link href={href}>{React.cloneElement(child, { className })}</Link>; }; ActiveLink.propTypes = { href: PropTypes.string, activeClassName: PropTypes.string, children: PropTypes.node.isRequired }; ActiveLink.defaultProps = { href: '', activeClassName: '' }; export default ActiveLink;
Thanks a lot, for use:
<NavLink href = "/path" activeClassName = "--active">
    <a className="classes">
        Home Page
    </a>
</NavLink>Hello , work for me .
find on SO https://stackoverflow.com/questions/53262263/target-active-link-when-the-route-is-active-in-next-js :
import Link from "next/link";
import { useRouter } from "next/router";
export const MyNav = () => {
  const router = useRouter();
  return (
    <ul>
      <li className={router.pathname == "/" ? "active" : ""}>
        <Link href="/">home</Link>
      </li>
      <li className={router.pathname == "/about" ? "active" : ""}>
        <Link href="/about">about</Link>
      </li>
    </ul>
  );
};my code :
          <Link href="/">
            <a className={router.pathname ==="/" ? styles.navlinkActive : styles.navlink}>
              Accueil
            </a>
          </Link>All these look like great solutions, but regrettably I cannot make any to work reliably with this navbar structure:
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
import ActiveLink from '../CustomLink/ActiveLink';
export default function Navigation() {
  return (
    <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
      <ActiveLink activeClassName="active" href="/">
        <Navbar.Brand>
          <img src="/logo.svg" alt="WhiteQueen Logo" height={50} />
        </Navbar.Brand>
      </ActiveLink>
      <Navbar.Toggle aria-controls="responsive-navbar-nav" />
      <Navbar.Collapse id="responsive-navbar-nav">
        <Nav className="mr-auto">
          <ActiveLink activeClassName="active" href="/">
            <Nav.Link>Home</Nav.Link>
          </ActiveLink>
          <ActiveLink activeClassName="active" href="/publications">
            <Nav.Link>Publications</Nav.Link>
          </ActiveLink>
          <ActiveLink activeClassName="active" href="/links">
            <Nav.Link>Links</Nav.Link>
          </ActiveLink>
        </Nav>
        <Nav>
          <ActiveLink activeClassName="active" href="/contact">
            <Nav.Link>Contact</Nav.Link>
          </ActiveLink>
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  );
}If I click on a link nested in a different <Nav> (for example, "Contact") the highlighting of the previous one isn't removed...
Am I missing something obvious?
I rather have my own function that creates a pure next/link component:
import Link from "next/link";
import {useRouter} from "next/router";
import styles from './Toolbar.module.css'
const Toolbar = () => {
    const router = useRouter();
    const activeLink = (path, content, activeClass = styles.active, normalClass = '') => {
        let className = router.pathname === path ? activeClass : normalClass;
        return <Link href={path}><a className={className}>{content}</a></Link>
    }
    return <div className={styles.toolbar}>
        <nav>
            {activeLink('/', 'Home')}
            {activeLink('/about', 'About')}
        </nav>
    </div>
}
export default Toolbar;If you need a more reusable function, you can pass the router:
import Link from "next/link"
const createActiveLink = (router, path, content, activeClass = 'active', normalClass = '') => {
      let className = router.pathname === path ? activeClass : normalClass;
      return <Link href={path}><a className={className}>{content}</a></Link>
  }
export default createActiveLinktyped. 21/10/22
Thank you very much remy san XD
import { withRouter, NextRouter  } from 'next/router';
import React, { ReactElement } from 'react';
import Link from 'next/link';
type Props = {
  router: NextRouter;
  children: ReactElement;
  href: string;
  activeClassName: string;
}
const ActiveLink = ({ router, children, ...props }: Props) => {
  const child = children;
  
  let className: string = child.props.className;
  if (router.pathname == props.href) {
    className = `${className} ${props.activeClassName}`;
  }
  return (
  <Link {...props}>{React.cloneElement(child, { className })}</Link>
  );
}
export default withRouter(ActiveLink);Here's my version of ActiveLink for Next.js + TypeScript:
import Link, { LinkProps } from "next/link";
import { NextRouter, useRouter } from "next/router";
import { FC, PropsWithChildren } from "react";
type ActiveLinkProps = LinkProps & {
  activeClassName: string;
  className: string;
};
export const ActiveLink: FC<ActiveLinkProps> = ({ children, ...props }: PropsWithChildren<ActiveLinkProps>) => {
  const router: NextRouter = useRouter();
  const className: string =
    props.className + ((router.pathname === props.href && props.activeClassName) ? " " + props.activeClassName : "");
  return (
    <Link {...props}>
      <a className={className}>{children}</a>
    </Link>
  );
};Example of usage:
          <ActiveLink href="/" className="menulink" activeClassName="active">
            Home
          </ActiveLink>The difference is you no longer need <a> tag inside.
Benefits:
- TypeScript-friendly
- You no longer need to find child element and its type with Children.only
- You no longer need to do React.cloneElement
- You won't forget to put <a>inside anymore.

Awesome, thanks a lot! Here is my more minimal version for when the className does not have to be set using a prop: