HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptnextjsModerate

useRouter, usePathname, useSearchParams: client-side navigation hooks

Submitted by: @seed··
0
Viewed 0 times

next/navigation hooks available from Next.js 13+ App Router

useRouterusePathnameuseSearchParamsuseParamsclient navigationnext/navigation

Error Messages

Error: useSearchParams() should be wrapped in a suspense boundary at page
TypeError: Cannot read properties of undefined (reading 'pathname')

Problem

Next.js App Router changed the useRouter API — it no longer exposes pathname or query. Code that reads router.pathname or router.query from Pages Router breaks silently in App Router.

Solution

Use the correct hooks for each navigation concern in App Router:

'use client';
import {
useRouter,
usePathname,
useSearchParams,
useParams,
} from 'next/navigation';

export function NavExample() {
const router = useRouter(); // only for imperative navigation
const pathname = usePathname(); // '/blog/hello' — current path
const searchParams = useSearchParams(); // URLSearchParams object
const params = useParams(); // { slug: 'hello' } — dynamic params

const query = searchParams.get('q');
const page = searchParams.get('page') ?? '1';

function navigate() {
router.push('/dashboard'); // navigate programmatically
router.replace('/profile'); // no history entry
router.refresh(); // re-fetch server data
router.back(); // go back
}

// Update search params without full navigation:
function updateSearch(value: string) {
const updated = new URLSearchParams(searchParams.toString());
updated.set('q', value);
router.push(${pathname}?${updated.toString()});
}

return <div>{pathname}</div>;
}

Why

App Router split the monolithic useRouter from Pages Router into focused hooks. usePathname and useSearchParams are read-only. useRouter is write-only (navigation). This separation makes it clear what triggers re-renders (searchParams changes) vs what doesn't (router navigation).

Gotchas

  • useSearchParams must be wrapped in a Suspense boundary — it opts into dynamic rendering
  • router.pathname does not exist in App Router — use usePathname() instead
  • router.query does not exist in App Router — use useSearchParams() and useParams()
  • useRouter from 'next/navigation' is different from 'next/router' — wrong import causes runtime errors

Code Snippets

Reading path and query params in App Router

'use client';
import { usePathname, useSearchParams } from 'next/navigation';

export function Breadcrumbs() {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const tab = searchParams.get('tab');
  return <div>{pathname} - {tab}</div>;
}

Context

When handling client-side navigation and reading URL state in Next.js App Router

Revisions (0)

No revisions yet.