the complete guide to back buttons in next.js - By Sourav Mishra (@souravvmishra)
back buttons seem simple, but in next.js there are some tricks. here is how to build one that always works.
back buttons sound super easy, right? well, in next.js there are a few things you gotta get right.
let's see how to do it properly.
the basic ways
you have two main options for this.
1. using router.back()
this is the most common way, using the useRouter hook.
"use client";
import { useRouter } from "next/navigation";
export const BackButton = () => {
const router = useRouter();
return (
<button onClick={() => router.back()}>
go back
</button>
);
};
things to know:
- you need
"use client"because hooks don't run on the server. - it uses the browser's history.
- if there is no history (like a direct link), it does nothing.
2. using window.history.back()
for simple stuff without hooks:
"use client";
export const BackButton = () => {
return (
<button onClick={() => window.history.back()}>
go back
</button>
);
};
it does the exact same thing but saves you an import.
the direct access problem
what if someone opens your link directly from google? there's no history to go back to.
the fallback fix
"use client";
import { useRouter } from "next/navigation";
export const BackButton = ({ fallbackUrl = "/" }) => {
const router = useRouter();
const handleBack = () => {
if (window.history.length > 1) {
router.back();
} else {
router.push(fallbackUrl);
}
};
return (
<button onClick={handleBack}>
go back
</button>
);
};
what if i just want a hardcoded link?
if you always want to go back to the exact same page, just use a normal <Link>.
import Link from "next/link";
export default function BlogPost() {
return (
<article>
<Link href="/blog">back to blog</Link>
{/* content */}
</article>
);
}
use
router.back()when users can come from multiple pages. use<Link>when the destination is always fixed.
common mistakes
- forgetting
"use client": hooks crash server components. - no fallback: users get stuck if they open a direct link.
- hydration issues: don't check
window.historyduring render, only in the click handler.
just stick to the fallback logic and you'll be fine. lol.