6 - Изменение query params с useRouter, usePathname и useSearchParams

Для доступа к видео войдите в систему

6 - Изменение query params с useRouter, usePathname и useSearchParams

Оценить качество материала и подачу материала автором видео:

Front-end

Трудоустройтесь middle front-end разработчиком на React JS (TypeScript) за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Front-end

Back-end

Трудоустройтесь middle back-end разработчиком за 12-16 месяцев обучения с ежедневной менторской поддержкой в формате видео 1 на 1 и коммерческими проектами в портфолио

Перейти на курс
Back-end

Карьерный бустер

Получите коммерческий опыт на реальных стартапах, прокачайте tech & soft навыки, научитесь работать в команде, проходить собеседования и получите первую работу в IT!

Перейти на курс
Карьерный бустер

Основы Front-end

Сделайте первый шаг в IT, освоив базовые знания разработки и научившись создавать небольшие проекты на JavaScript

Перейти на курс
Основы Front-end

Основы Back-end

Сделайте первый шаг в IT, освоив базовые знания разработки. Без опыта. Без математики. Только практика: JavaScript, SQL, Node JS, база данных

Перейти на курс
Основы Back-end

Изменение query params с useRouter, usePathname и useSearchParams

Автор конспекта: Стогниева Виктория

Введение: Что такое параметры запроса и зачем они нужны? 🎯

Представьте, что URL-адрес страницы — это название книги, а параметры запроса (query-параметры) — это заметки на полях, которые вы оставляете. Основное название книги не меняется, но заметки помогают вам уточнить, на что именно обратить внимание: ?страница=42&глава=3. В вебе они работают точно так же.

Ключевая задача: передача дополнительной информации (сортировка, фильтры, поисковые запросы) через URL без изменения основного адреса страницы.

Пример: mysite.com/products?category=laptops&sort=price_desc

В современной разработке на Next.jsApp Router) для работы с URL используются три основных инструмента (хука):

ХукНазначение
useRouterДля программной навигации
usePathnameДля чтения основного пути URL
useSearchParamsДля чтения параметров запроса
💡

Экспертная заметка: В старом Pages Router информация о текущем пути была частью единого хука useRouter. В App Router эту логику намеренно разделили на специализированные хуки для повышения производительности и улучшения code splitting. Теперь компоненты перерисовываются только при изменении той части URL, от которой они напрямую зависят.

1. Читаем URL: Знакомство с usePathname и useSearchParams 📖

Хук usePathname — Где мы находимся?

У этого хука одна простая задача: получить текущий путь в адресной строке без домена и без query-параметров.

Пример: Если полный URLhttps://example.com/profile/123?active=true, то usePathname вернет только /profile/123.

jsx
import { usePathname } from "next/navigation"
 
function CurrentPath() {
  const pathname = usePathname() // Получаем '/profile/123'
 
  return <div>Текущий путь: {pathname}</div>
}

Хук useSearchParams — Что написано в "заметках на полях"?

💡

Этот хук предназначен исключительно для чтения query-параметров. Он позволяет проверить, есть ли в URL определенный параметр, или получить его значение

💡

Важное ограничение: Объект, возвращаемый useSearchParams, предназначен только для чтения. У него нет методов для изменения, добавления или удаления параметров.

Но как же изменять параметры? Прямо — никак. Потребуется другой подход.🤔

2. Главный секрет: изменение URL через навигацию🧩

Основная идея: изменение query-параметров — это не модификация текущего URL, а перенаправление на новый адрес. Даже если адрес отличается одним символом в параметрах, для Next.js это переход на "другую" страницу.

Два способа выполнения перехода:

ИнструментОписание
<Link>Декларативный способ. Создает стандартный тег <a>. Семантически корректен, индексируется поисковыми системами, позволяет использовать стандартное поведение браузера. Идеален для навигации.
router.pushИмперативный способ. Позволяет программно выполнить переход на новый URL (по клику на кнопку, после выполнения логики и т.д.).

3. Собираем всё вместе: практический рецепт 🍳

Это официально рекомендованный подход из документации Next.js для управления состоянием URL в App Router.

  1. Шаг 1: Получаем "ингредиенты". Внутри вашего компонента импортируем и вызываем все три хука: useRouter, usePathname и useSearchParams.

  2. Шаг 2: Готовим новые параметры. С помощью встроенного в браузер конструктора URLSearchParams мы создаем новый, изменяемый набор параметров.

  • Почему new URLSearchParams(searchParams.toString())? Хук useSearchParams возвращает read-only (только для чтения) объект. Чтобы создать его изменяемую копию, мы сначала превращаем текущие параметры в строку (searchParams.toString()), а затем передаем эту строку в конструктор new URLSearchParams(). В результате мы получаем новый, полностью управляемый объект.
  1. Шаг 3: Собираем новый URL. Мы объединяем pathname (из usePathname) с новой строкой параметров, чтобы получить полный целевой адрес.

  2. Шаг 4: Выполняем переход. Используем полученный URL в <Link> или передаем его в router.push.

Пример 1: Изменение URL с помощью кнопки и router.push

Представим, что мы хотим добавить параметр title=book к текущему URL по нажатию на кнопку. Следуя лучшим практикам, вынесем логику создания URL в отдельную функцию.

tsx
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useCallback } from "react"
import styles from "./header.module.css"
 
export const Header = () => {
  const router = useRouter()
  const searchParams = useSearchParams()
  const pathname = usePathname()
 
  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams.toString())
      params.set(name, value)
      return params.toString()
    },
    [searchParams],
  )
 
  return (
    <nav className={styles.navigation}>
      <button
        onClick={() => {
          router.push(pathname + "?" + createQueryString("sort", "asc"))
        }}
      >
        ASC
      </button>
      <ul>
        <li>
          <button onClick={() => router.push("/", { scroll: false })} className={styles.link}>
            Main
          </button>
        </li>
        <li>
          <button
            onClick={() => router.push("/profile", { scroll: false })}
            className={styles.link}
          >
            Profile
          </button>
        </li>
        <li>
          <button
            onClick={() => router.push("/profile/123", { scroll: false })}
            className={styles.link}
          >
            Profile 123
          </button>
        </li>
      </ul>
    </nav>
  )
}

При нажатии на кнопку произойдет редирект на тот же путь, но с добавленным ?title=book.

Пример 2: Изменение URL с помощью ссылки <Link>

Результат будет абсолютно идентичным, но реализация будет декларативной. Мы заранее готовим URL для ссылки, используя ту же логику.

tsx
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useCallback } from "react"
import styles from "./header.module.css"
 
export const Header = () => {
  const router = useRouter()
  const searchParams = useSearchParams()
  const pathname = usePathname()
 
  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams.toString())
      params.set(name, value)
      return params.toString()
    },
    [searchParams],
  )
 
  return (
    <nav className={styles.navigation}>
      <Link href={pathname + "?" + createQueryString("title", "book")}>book</Link>
      <ul>
        <li>
          <button onClick={() => router.push("/", { scroll: false })} className={styles.link}>
            Main
          </button>
        </li>
        <li>
          <button
            onClick={() => router.push("/profile", { scroll: false })}
            className={styles.link}
          >
            Profile
          </button>
        </li>
        <li>
          <button
            onClick={() => router.push("/profile/123", { scroll: false })}
            className={styles.link}
          >
            Profile 123
          </button>
        </li>
      </ul>
    </nav>
  )
}

Этот подход более предпочтителен для простой навигации, так как он семантически верный и не требует JavaScript для обработки клика.

4. Ключевые выводы 🎓

Давайте подведем итоги и закрепим материал.

  1. 📖 Хук useSearchParams только читает параметры из URL. Он не предназначен для их изменения.
  2. ✏️ Изменение query-параметров всегда происходит через перенаправление с помощью компонента <Link> или метода router.push.
  3. 🧩 Связка хуков useRouter, usePathname и useSearchParams является стандартным и рекомендуемым способом для динамического управления URL в современных приложениях на Next.js.