Как работать с query-параметрами на React?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Легкий
#React

Краткий ответ

Для работы с query-параметрами в React используйте хук useSearchParams из React Router или библиотеку query-string 🔍

// React Router v6
import { useSearchParams } from 'react-router-dom';
 
function App() {
  const [searchParams, setSearchParams] = useSearchParams();
  const query = searchParams.get('search');
  
  return (
    <div>
      <p>Поисковый запрос: {query}</p>
      <button onClick={() => setSearchParams({ search: 'новый запрос' })}>
        Изменить запрос
      </button>
    </div>
  );
}

Полный ответ

Query-параметры — это часть URL после знака вопроса (например, ?search=react&page=1) 🌐

Способ 1: React Router (рекомендуется)

Самый простой способ для современных React-приложений — использовать хук useSearchParams из React Router 🛣️

import { useSearchParams } from 'react-router-dom';
 
function SearchPage() {
  // Получаем текущие параметры и функцию для их изменения
  const [searchParams, setSearchParams] = useSearchParams();
  
  // Получаем значения параметров
  const query = searchParams.get('search') || '';
  const page = searchParams.get('page') || '1';
  
  // Обработчик изменения поиска
  const handleSearch = (newQuery) => {
    setSearchParams({ search: newQuery, page: '1' });
  };
  
  // Обработчик изменения страницы
  const handlePageChange = (newPage) => {
    setSearchParams({ search: query, page: newPage });
  };
  
  return (
    <div>
      <input 
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
        placeholder="Поиск..."
      />
      <p>Страница: {page}</p>
      <button onClick={() => handlePageChange(String(Number(page) + 1))}>
        Следующая страница
      </button>
    </div>
  );
}

Способ 2: query-string (без роутера)

Если вы не используете React Router, можно использовать библиотеку query-string 📦

import { useState, useEffect } from 'react';
import queryString from 'query-string';
 
function SearchComponent() {
  // Парсим текущие параметры из URL
  const parsed = queryString.parse(window.location.search);
  const [query, setQuery] = useState(parsed.search || '');
  
  // Обновляем URL при изменении запроса
  const updateUrl = (newQuery) => {
    const newParams = queryString.stringify({ search: newQuery });
    window.history.pushState({}, '', `?${newParams}`);
  };
  
  return (
    <div>
      <input 
        value={query}
        onChange={(e) => {
          setQuery(e.target.value);
          updateUrl(e.target.value);
        }}
        placeholder="Поиск..."
      />
    </div>
  );
}

Способ 3: Простой кастомный хук

Можно создать свой хук для работы с URL-параметрами 🪝

import { useState, useCallback, useEffect } from 'react';
 
function useQueryParam(key) {
  // Функция для получения значения параметра
  const getParam = useCallback(() => {
    const params = new URLSearchParams(window.location.search);
    return params.get(key) || '';
  }, [key]);
  
  // Состояние для хранения значения
  const [value, setValue] = useState(getParam());
  
  // Функция для обновления параметра
  const updateParam = useCallback((newValue) => {
    const params = new URLSearchParams(window.location.search);
    
    if (newValue) {
      params.set(key, newValue);
    } else {
      params.delete(key);
    }
    
    window.history.pushState(
      {}, 
      '', 
      `${window.location.pathname}?${params.toString()}`
    );
    
    setValue(newValue);
  }, [key]);
  
  // Слушаем изменения URL
  useEffect(() => {
    const handlePopState = () => setValue(getParam());
    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, [getParam]);
  
  return [value, updateParam];
}
 
// Использование
function SearchComponent() {
  const [search, setSearch] = useQueryParam('search');
  
  return (
    <input 
      value={search}
      onChange={(e) => setSearch(e.target.value)}
      placeholder="Поиск..."
    />
  );
}

Полезные советы

1. Получение нескольких параметров

// С React Router
const [searchParams] = useSearchParams();
 
// Получаем все параметры сразу
const allParams = Object.fromEntries(searchParams.entries());
console.log(allParams); // { search: 'react', page: '1' }
 
// Проверяем наличие параметра
const hasFilter = searchParams.has('filter');

2. Сохранение предыдущих параметров

const [searchParams, setSearchParams] = useSearchParams();
 
// Сохраняем существующие параметры при обновлении
const updatePage = (newPage) => {
  const current = Object.fromEntries(searchParams.entries());
  setSearchParams({ ...current, page: newPage });
};

3. Отслеживание изменений параметров

const [searchParams] = useSearchParams();
 
// Используем useEffect для реакции на изменения
useEffect(() => {
  const currentQuery = searchParams.get('search');
  // Выполняем поиск при изменении запроса
  if (currentQuery) {
    fetchResults(currentQuery);
  }
}, [searchParams]); // Зависимость от searchParams

Частые ошибки

Забывать преобразовывать типы

// ❌ Ошибка — параметры всегда строки
const page = searchParams.get('page');
const nextPage = page + 1; // '11' вместо 2, если page='1'
 
// ✅ Правильно — преобразуем в число
const page = Number(searchParams.get('page') || '1');
const nextPage = page + 1; // 2, если page='1'

Не учитывать отсутствие параметров

// ❌ Ошибка — параметр может отсутствовать
const query = searchParams.get('search');
const firstLetter = query.charAt(0); // Ошибка, если query=null
 
// ✅ Правильно — проверяем наличие
const query = searchParams.get('search') || '';
const firstLetter = query.charAt(0); // Безопасно

Простые правила

  1. React Router — лучший выбор для большинства проектов 🥇
  2. URLSearchParams — встроенный API для простых случаев 🔧
  3. query-string — удобная библиотека для сложных случаев 📚
  4. Всегда проверяйте наличие параметров перед использованием ✅
  5. Не забывайте о преобразовании типов (строка → число) 🔄
  6. Используйте useEffect для реакции на изменения параметров 🔄

Понимание работы с query-параметрами делает ваши React-приложения более функциональными и удобными! 💪


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪