const updateParams = (updates: Record) => {
// Create new URLSearchParams from current params
const params = new URLSearchParams(searchParams.toString());
// Apply updates
Object.entries(updates).forEach(([key, value]) => {
if (value) {
params.set(key, value);
} else {
params.delete(key); // Remove if value is empty
}
});
// Navigate with new params
router.push(`?${params.toString()}`);
};
return (
);
}
Common Patterns
Pattern: Search with Debounce
'use client';
import { Suspense, useState, useEffect } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { useSearchParams } from 'next/navigation';
export default function Page() {
const searchParams = useSearchParams(); // Will cause issues!
return
{searchParams.get('q')}
;
}
// ✅ CORRECT
'use client';
import { Suspense } from 'react';
import { useSearchParams } from 'next/navigation';
function SearchContent() {
const searchParams = useSearchParams();
return
{searchParams.get('q')}
;
}
export default function Page() {
return (
Loading...\
}>
);
}
❌ Mistake 3: Using in Server Component
// ❌ WRONG - Trying to use in server component
import { useSearchParams } from 'next/navigation';
export default async function Page() { // async = server component
const searchParams = useSearchParams(); // ERROR! Hooks don't work in server components
return
...
;
}
// ✅ CORRECT - Use searchParams prop in server components
export default async function Page({
searchParams,
}: {
searchParams: Promise<{ q?: string }>;
}) {
const { q } = await searchParams;
return
Query: {q}
;
}
Server vs Client searchParams
Feature Server Component Client Component
Access method searchParams prop useSearchParams() hook
Requires 'use client' ❌ No ✅ Yes
Requires Suspense ❌ No ✅ Yes
Can be async ✅ Yes ❌ No
Can update params ❌ No (use Link/redirect) ✅ Yes (use router.push)
Best for Initial load, SEO Dynamic filters, real-time updates
Quick Checklist
When using useSearchParams:
Add 'use client' directive at top of file
Import Suspense from 'react'
Import useSearchParams from 'next/navigation'
Wrap component using useSearchParams in
Provide a fallback to Suspense
Call useSearchParams() inside wrapped component
Use .get(), .has(), or .getAll() to read params
Summary
useSearchParams with Suspense:
✅ Requires 'use client' directive
✅ Requires wrapper
✅ Use for client-side URL param reading
✅ Combine with useRouter() for updating params
✅ Best for filters, search, pagination
❌ NOT for server components (use searchParams prop instead)
This is the recommended pattern for client-side URL parameter handling in Next.js App Router.