Retrieving Query Parameters in Next.js Server Components
Problem Statement
Next.js 13 introduced the app
directory architecture where components are server components by default. While server components provide direct access to features like cookies()
and headers()
, there's no built-in method to access URL query parameters like ?name=value
in arbitrary server components. This creates challenges when you need to react to dynamic URL parameters without traditional approaches like getServerSideProps
.
Recommended Solutions
1. Accessing Query Parameters in Page Components
Page components (page.tsx
) receive query parameters via the searchParams
prop:
export default function Page({
searchParams,
}: {
searchParams?: { [key: string]: string | string[] | undefined };
}) {
const filter = searchParams?.filter || 'default'; // Access ?filter=value
const sort = searchParams?.sort || 'asc'; // Access ?sort=value
return <div>Filter: {filter}, Sort: {sort}</div>;
}
Notes:
- This is the standard approach for page components
- Works similarly in
layout.tsx
andtemplate.tsx
- Automatically handles both static and dynamic routes
2. Using URLSearchParams API in Route Handlers
For API routes (route.ts
), parse query parameters using the browser's native URL
and URLSearchParams
:
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get('q');
const page = searchParams.get('page') || '1';
// Return results based on query paramters
return Response.json({ results: [] });
}
3. Sharing Query Parameters via Middleware
Access query parameters in any server component by propagating URL information through request headers:
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-url', request.url);
return NextResponse.next({
request: { headers: requestHeaders }
});
}
Then in any server component:
import { headers } from 'next/headers';
export default function Component() {
const url = headers().get('x-url') || '';
const searchParams = new URL(url).searchParams;
const theme = searchParams.get('theme'); // Access ?theme=value
// ...
}
Alternative Approaches
Type-Safe Query Parameters with NUQS
For complex query parameter handling in server components:
import { parseAsString, createSearchParamsCache } from 'nuqs/server';
const cache = createSearchParamsCache({
theme: parseAsString.withDefault('light'),
pageIndex: parseAsString.withDefault('0')
});
export default function Page({ searchParams }) {
const { theme, pageIndex } = cache.parse(searchParams);
return <div>Theme: {theme}, Page: {pageIndex}</div>;
}
Third-Party Consideration
While NUQS provides type safety and parsing utilities, evaluate whether your use case justifies adding external dependencies.
Parsing Query Parameters Manually
Utility functions for custom parsing logic:
export function parseQuery(url: string) {
const searchParams = new URLSearchParams(new URL(url).search);
return Object.fromEntries(searchParams.entries());
}
// Usage in server components
const query = parseQuery(headers().get('x-url') || '');
When to Use
- Requires custom query parameter handling
- Works across both server and client components
Key Implementation Details
- Component Hierarchy Considerations
- Only pass
searchParams
to client components as needed - Avoid deeply nested propagation when possible
- Only pass
// Pass only necessary values to client components
<ClientComponent filter={searchParams?.filter} />
- Edge Cases
- Handle array parameters:
?ids=1&ids=2
- Manage encoding/decoding
- Consider URL length limits
- Handle array parameters:
// Handling array parameters
const ids = searchParams.id
? Array.isArray(searchParams.id)
? searchParams.id
: [searchParams.id]
: [];
Conclusion
While Next.js provides direct searchParams
access in page/layout components, other server components require either:
- Middleware propagation via headers
- Parameter passing through props
- Third-party libraries like NUQS
For API routes, use the native URL
API for reliable parameter parsing. The optimal approach depends on whether you're working with page components, API handlers, or generic server components.
Version Compatibility
These solutions apply to Next.js 13+ and leverage features available as of Next.js 15. Verify compatibility with your project's specific version.