Next.js onClick Handlers: The Ultimate Guide
If you've just moved to the Next.js App Router and your buttons are throwing errors like "Event handlers cannot be passed to Client Component props," you aren't alone.
Handling onClick in Next.js has changed. This guide will show you the modern way to handle interactivity while keeping your app fast and SEO-friendly.
[FREE DOWNLOAD] The Next.js App Router Interactivity Cheat Sheet
Stop fighting 'use client' errors. Get the 5 patterns I use to handle state and events without bloating your client bundle. Download the Cheat Sheet Here (Lead Magnet Placeholder)
The #1 Mistake: Forgetting 'use client'
In the Next.js App Router, components are Server Components by default. Server Components are rendered on the server and cannot handle browser events like onClick.
To use a button with a click handler, you must add the "use client"; directive at the very top of your file.
Modern App Router Example
// components/InteractiveButton.tsx
"use client";
export default function InteractiveButton() {
const handleClick = () => {
alert("Button clicked in the browser!");
};
return (
<button
onClick={handleClick}
className="px-4 py-2 bg-blue-600 text-white rounded-md"
>
Click Me
</button>
);
}
The "Server-to-Client" Pattern
A common business requirement is fetching data on the server but handling clicks on the client. You should keep your data fetching in a Server Component and pass only the necessary data to an Interactive Client Component.
// app/page.tsx (Server Component)
import InteractiveButton from './components/InteractiveButton';
export default function Page() {
return (
<main>
<h1>Product Dashboard</h1>
{/* The button handles interactivity, the page stays a Server Component */}
<InteractiveButton />
</main>
);
}
Navigating on Click (The Right Way)
Don't use window.location.href. In Next.js, use the useRouter hook from next/navigation for a seamless SPA-like transition.
"use client";
import { useRouter } from 'next/navigation';
export default function NavButton() {
const router = useRouter();
return (
<button onClick={() => router.push('/dashboard')}>
Go to Dashboard
</button>
);
}
Building a Complex Next.js App?
Handling interactivity at scale is hard. I help teams migrate legacy React apps to the Next.js App Router while improving Core Web Vitals. Book a 15-minute consulting discovery call
Common Errors & FAQs (SEO)
Error: "Event handlers cannot be passed to Client Component props"
This happens when you try to pass a function (like onClick) from a Server Component to a Client Component. Solution: Define the function inside the Client Component or move the logic to a Server Action.
Can I use onClick in a Server Component?
No. All interactivity requires the browser's JavaScript engine. You must use a Client Component for onClick, onScroll, useState, or useEffect.
How do I track button clicks in Next.js?
You can trigger analytics (like Google Analytics or PostHog) inside the onClick handler of a Client Component.
Conclusion
Mastering onClick in Next.js is about understanding the boundary between the server and the client. By keeping your interactivity isolated in small Client Components, you ensure your application remains high-performance.
Happy coding!