Skip to content

Instantly share code, notes, and snippets.

@webowodev
Last active May 8, 2025 01:09
Show Gist options
  • Select an option

  • Save webowodev/c0e8abf5e78f36d5ea5e24cd028b3174 to your computer and use it in GitHub Desktop.

Select an option

Save webowodev/c0e8abf5e78f36d5ea5e24cd028b3174 to your computer and use it in GitHub Desktop.
NextJS Route History Provider to prevent user go outside our app when navigate back
// your back button component
// components/backButton.tsx
'use client';
import { ArrowLeft } from "@phosphor-icons/react";
import { Button } from "./ui/button";
import useRouteHistory from "@/hooks/use-route-history";
import { useRouter } from "next/navigation";
type Props = {
fallback?: string;
fallbackMethod?: 'replace' | 'push';
}
export default function BackButton({ fallback, fallbackMethod = 'replace' }: Props) {
const router = useRouter();
const history = useRouteHistory();
const handleBack = async () => {
if (history?.previousRoute) {
router.back();
} else {
router[fallbackMethod](fallback ?? '/');
}
}
return (
<Button size={'icon'} variant={'ghost'} className={'rounded-full active:bg-accent'} onClick={handleBack}>
<ArrowLeft weight="bold" />
</Button>
);
}
// on your root layout /app/layout.tsx
// ...
export default function RootLayout({children}: {children: React.ReactNode}) {
return <RouteHistoryProvider>
{children}
</RouteHistoryProvider>;
}
// providers/routeHistory.tsx
'use client';
import { usePathname } from "next/navigation";
import { createContext, useEffect, useRef } from "react";
export type IRouteHistoryContext = {
previousRoute: string | null;
}
export const RouteHistoryContext = createContext<IRouteHistoryContext>({} as IRouteHistoryContext);
const RouteHistoryProvider = ({ children }: { children: React.ReactNode }) => {
const pathname = usePathname();
const ref = useRef<string | null>(null);
useEffect(() => {
ref.current = pathname;
}, [pathname]);
return <RouteHistoryContext.Provider value={{ previousRoute: ref.current }}>
{children}
</RouteHistoryContext.Provider>
};
export default RouteHistoryProvider;
// /hooks/use-route-history.ts
import {
IRouteHistoryContext,
RouteHistoryContext,
} from "@/providers/routeHistoryProvider";
import { useContext } from "react";
const useRouteHistory = () => {
const context = useContext<IRouteHistoryContext | null>(RouteHistoryContext);
return context;
};
export default useRouteHistory;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment