Skip to the solution
EasyFrontend9 min read

How do you read the current URL in a Next.js Client Component (usePathname, useSearchParams, useParams)?

211 views

The problem

Question presented to candidate: "You are building a product listing page in the App Router. Inside a Client Component you need the current path, the query string and the dynamic route values. Which hooks do you use, what does each return, and what goes wrong if you are careless with them?"

What a strong answer should cover:

  • All three come from next/navigation and only work in Client Components ('use client').
  • usePathname() returns the path string without the query; useSearchParams() returns a read-only URLSearchParams (get, getAll, has); useParams() returns the dynamic segments, with arrays for catch-all routes and {} when there are none.
  • They update on client navigation, which is why they work inside layouts where server props would go stale.
  • On a prerendered route, useSearchParams cannot know the query at build time, so the component must sit inside <Suspense> or the build fails; with Cache Components the same applies to usePathname and useParams for params not covered by generateStaticParams.
  • In a Server Component use the page params and searchParams props instead; to change the query, build a new URLSearchParams and call router.push/replace or render a Link.

Clarifying questions expected:

  • "Is the page prerendered or rendered per request?" β€” it decides whether a Suspense boundary is required.
  • "Should a filter change add a history entry?" β€” push versus replace.

Code / implementation expected: Yes β€” a Client Component reading the three values, and updating one query parameter.

  • nextjs
  • navigation
  • hooks
  • client-components

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 10 sections

Read the code

Reading all three parts of the URL
// app/shop/[category]/[item]/ItemInfo.tsx
"use client";
import { useParams, usePathname, useSearchParams } from "next/navigation";

export default function ItemInfo() {
  const pathname = usePathname();         // "/shop/shoes/air-max"
  const searchParams = useSearchParams(); // read-only URLSearchParams for "?color=red&size=42"
  const params = useParams<{ category: string; item: string }>(); // { category: "shoes", item: "air-max" }

  return (
    <dl>
      <dt>Path</dt><dd>{pathname}</dd>
      <dt>Colour</dt><dd>{searchParams.get("color") ?? "any"}</dd>
      <dt>Sizes</dt><dd>{searchParams.getAll("size").join(", ") || "none"}</dd>
      <dt>Item</dt><dd>{params.item} in {params.category}</dd>
    </dl>
  );
}
Updating a query parameter and wrapping the hook in Suspense
// app/shop/SortButtons.tsx
"use client";
import { usePathname, useRouter, useSearchParams } from "next/navigation";

export default function SortButtons() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  function setSort(sort: "asc" | "desc") {
    const next = new URLSearchParams(searchParams.toString()); // copy: the hook value is read-only
    next.set("sort", sort);
    router.replace(`${pathname}?${next.toString()}`);
  }

  return (
    <div>
      <button onClick={() => setSort("asc")}>Price up</button>
      <button onClick={() => setSort("desc")}>Price down</button>
    </div>
  );
}

// app/shop/layout.tsx β€” Server Component
import { Suspense } from "react";
import SortButtons from "./SortButtons";

export default function ShopLayout({ children }: { children: React.ReactNode }) {
  return (
    <section>
      {/* Lets the rest of the route be prerendered; the buttons fill in on the client */}
      <Suspense fallback={<div>Loading filters...</div>}>
        <SortButtons />
      </Suspense>
      {children}
    </section>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 15 of 129 in Next.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Next.js questions
Up nextEasy

How do sitemap.ts and robots.ts work in Next.js?

Continue