A custom React hook to retrieve placeholder paths in Next.js App Router.
Next.js 13+ App Router doesn't provide a built-in method to return the path of placeholder values, unlike router.pathname
in Pages Router. This hook fills that gap, allowing you to get the placeholder path in the App Router, similar to how you would in the Pages Router.
For developers migrating from Pages Router to App Router, this hook can significantly reduce the pain points associated with the transition. It provides a familiar way to access placeholder paths, making it easier to port existing code and maintain consistency in your application's routing logic. By offering functionality similar to router.pathname
, usePlaceholderPath
helps bridge the gap between the two routing systems, allowing for a smoother migration process and reducing the need for extensive refactoring of route-dependent code.
npm install @sect/use-placeholder-path
# or
yarn add @sect/use-placeholder-path
# or
pnpm add @sect/use-placeholder-path
'use client';
import usePlaceholderPath from '@sect/use-placeholder-path';
const MyComponent = () => {
const placeholderPath = usePlaceholderPath();
return (
<div>
<p>Current placeholder path: {placeholderPath}</p>
</div>
);
}
export default MyComponent;
usePlaceholderPath(options?: UsePlaceholderPathOptions): string
interface UsePlaceholderPathOptions {
optionalCatchAllSegments?: string;
}
optionalCatchAllSegments
: (optional) The name of the optional catch-all segment. If provided, enables handling of top-level optional catch-all segments.
- Route:
/users/123/posts/456
- Result:
/users/[userId]/posts/[postId]
- Catch-all route:
/blog/2024/08/15
- Result:
/blog/[...slug]
usePlaceholderPath
requires the use of a Client Component.
Top-Level Optional Catch-all Segments are expected to return /folderName/[[...segmentName]]
, but currently /folderName
is returned.
- Expected:
/shop/[[...slug]]
- Actual:
/shop
This is due to the technical limitations in detecting Top-Level Optional Catch-all Segments in the Next.js App Router.
To address this limitation, we've introduced an optional configuration:
const placeholderPath = usePlaceholderPath({
optionalCatchAllSegments: 'slug'
});
See CHANGELOG.
✌️
A little project by @sectsect