Reputation: 2957
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
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
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
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
Reputation: 1657
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
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
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