Next.js

Search

Implementing search functionality using URL query parameters in Next.js App Router.

Search Component: Updating the URL search params on user input.
📄app/components/Search.tsx
TSX
'use client';

import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { useTransition } from 'react';

export default function Search() {
  const searchParams = useSearchParams();
  const pathname = usePathname();
  const { replace } = useRouter();
  const [isPending, startTransition] = useTransition();

  function handleSearch(term: string) {
    const params = new URLSearchParams(searchParams);
    if (term) {
      params.set('query', term);
    } else {
      params.delete('query');
    }
    
    startTransition(() => {
      replace(`${pathname}?${params.toString()}`);
    });
  }

  return (
    <input
      type="text"
      placeholder="Search..."
      className="border p-2 rounded"
      onChange={(e) => handleSearch(e.target.value)}
      defaultValue={searchParams.get('query') || ''}
    />
  );
}
Server Component: Reading search params to fetch data.
📄app/page.tsx
TSX
import Search from './components/Search';
import { Suspense } from 'react';

export default async function Page({
  searchParams,
}: {
  searchParams?: { query?: string };
}) {
  const query = searchParams?.query || '';
  
  // Example data fetch based on search query
  // const data = await db.items.findMany({ where: { title: { contains: query } } });

  return (
    <main className="p-4">
      <h1 className="text-2xl font-bold mb-4">Item Search</h1>
      
      <Search />

      <Suspense key={query} fallback={<p>Loading results...</p>}>
        <div className="mt-4">
          <p>Showing results for: <strong>{query || 'All items'}</strong></p>
          {/* Render fetched data here */}
        </div>
      </Suspense>
    </main>
  );
}