dev_el
dev_el

Reputation: 2957

How do I pass an href to an onClick function in nextjs?

In the following code

import Link from "next/link";

export default function IndexPage() {
  const handleClick = (path) => {
    if (path === "/about") {
      console.log("I clicked on the About Page");
    }
    if (path === "/posts") {
      console.log("I clicked on the Posts Page");
    }
  };
  return (
    <div>
      Hello World.{" "}
      <Link onClick={() => handleClick("/about")} href="/about">
        <a>About</a>
      </Link>
      <Link onClick={() => handleClick("/posts")} href="/posts">
        <a>Posts</a>
      </Link>
    </div>
  );

Whenever the about or posts page is clicked, I'd like to console.log that I clicked on the page name. Right now, my current implementation does not console.log anything. What is wrong with my code?

Upvotes: 26

Views: 115658

Answers (6)

Anish Ali
Anish Ali

Reputation: 37

The best solution exist

<Link
    onClick={(e) => {
       if (!isPageExist.length) {
         e.preventDefault() // if you don't want to navigate
         toast.warning('upgrade your plan')
         return
        } else {
         // do what-ever you want before navigating
         }
       }}
      href={item.href}
    >
     <div>         
         <div className="flex flex-col">
          <p className="font-medium text-md">{item.type}</p>
         </div>
     </div>
</Link>

Upvotes: 0

user6221709
user6221709

Reputation:

As of November 2021 you can make the child a functional component, to use console log:

import Link from 'next/link'

// `onClick`, `href`, and `ref` need to be passed to the DOM element
// for proper handling
const MyButton = React.forwardRef(({ onClick, href }, ref) => {
  return (
    <a href={href} onClick={onClick} ref={ref}>
      Click Me
    </a>
  )
})

function Home() {
  return (
    <Link href="/about" passHref>
      <MyButton />
    </Link>
  )
}

export default Home

No idea why this needs to be this way.

Upvotes: 5

Emilie
Emilie

Reputation: 11

This is NextJs definition for Link

declare function Link(props: React.PropsWithChildren<LinkProps>): React.DetailedReactHTMLElement<{
    onMouseEnter?: React.MouseEventHandler<Element> | undefined;
    onClick: React.MouseEventHandler;
    href?: string | undefined;
    ref?: any;
}, HTMLElement>;
export default Link;

You can invoke your custom onClick to the Link's first child's onClick prop. To make it easy to use, we can create our own custom link that wraps nextJS's link.

// aLink.js

import Link from 'next/link'

export default function ALink({ href, onClick, label }) {
    return (
        <Link href={href}>
            <a onClick={() => onClick()}>{label}</a>
        </Link>
    )
}

And then import your own ALink instead of nextJS's link! // NavLink.js

import ALink from './aLink';

export default function Nav() {
    return (
        <nav>
            <ALink href='/' onClick={() => customOnClick() label='home' }/>
        </nav>
    )
}

Upvotes: 1

Mohamed Jakkariya
Mohamed Jakkariya

Reputation: 1657

2021-08 Answer

In NextJS,

I did something like that

 const Nav = () => {

  const handleLogoClick = async (e: React.MouseEvent<HTMLAnchorElement, MouseEvent> | undefined, url: string) => {
    e?.preventDefault();
    alert('clicked');
  };


     return (
            <a href="" onClick={(e) => handleLogoClick(e, '/')}>
              {shopData?.logo && <Logo src={shopData?.logo} loading="lazy" />}
            </a>
    )
 }

Upvotes: 6

user9052491
user9052491

Reputation: 308

You can move the onClick handler to the <a> tag.

import { useRouter } from "next/router";
import Link from "next/link";

export default function IndexPage() {
  const router = useRouter();

  const handleClick = (e, path) => {
    if (path === "/about") {
      console.log("I clicked on the About Page");
    }
    if (path === "/posts") {
      console.log("I clicked on the Posts Page");
    }
  };
  return (
    <div>
      Hello World.{" "}
      <Link href="/">
        <a onClick={(e) => handleClick(e, "/about")}>About</a>
      </Link>{" "}
      <Link href="/">
        <a onClick={(e) => handleClick(e, "/posts")}>Posts</a>
      </Link>
    </div>
  );
}

Upvotes: 26

yaiks
yaiks

Reputation: 640

updating answer to handle race condition between href and onClick

Since you are redirected when clicking the <Link>, I wouldn't try to manage both href and onClick.

I would do everything on the handleClick function, even redirecting the user in a programatically way:

import { useRouter } from 'next/router'

export default function IndexPage() {
  const router = useRouter()

  const handleClick = (e, path) => {
   e.preventDefault()

    if (path === "/about") {
      console.log("I clicked on the About Page");
      // then you can: 
      // router.push(path)
    }
    if (path === "/posts") {
      console.log("I clicked on the Posts Page");
      // then you can: 
      // router.push(path)
    }
  };
}

  return (
    <div>
      Hello World.{" "}
      <Link onClick={(e) => handleClick(e, "/about")}>
        <a>About</a>
      </Link>
      <Link onClick={(e) => handleClick(e, "/posts")}>
        <a>Posts</a>
      </Link>
    </div>
  );

Note that if you do router.push right after the console.log, the console.log would not be shown, since you are being redirected. But I believe you want to do some extra work before pushing the user, so you can follow this approach anyway.

Upvotes: 5

Related Questions