How to work with query parameters in React?

👨‍💻 Frontend Developer 🟠 May come up 🎚️ Easy
#React

Brief Answer

To work with query parameters in React, use the useSearchParams hook from React Router or the query-string library 🔍

// React Router v6
import { useSearchParams } from 'react-router-dom';
 
function App() {
  const [searchParams, setSearchParams] = useSearchParams();
  const query = searchParams.get('search');
  
  return (
    <div>
      <p>Search query: {query}</p>
      <button onClick={() => setSearchParams({ search: 'new query' })}>
        Change query
      </button>
    </div>
  );
}

Full Answer

Query parameters are the part of a URL after the question mark (e.g., ?search=react&page=1) 🌐

The easiest way for modern React applications is to use the useSearchParams hook from React Router 🛣️

import { useSearchParams } from 'react-router-dom';
 
function SearchPage() {
  // Get current parameters and function to change them
  const [searchParams, setSearchParams] = useSearchParams();
  
  // Get parameter values
  const query = searchParams.get('search') || '';
  const page = searchParams.get('page') || '1';
  
  // Search change handler
  const handleSearch = (newQuery) => {
    setSearchParams({ search: newQuery, page: '1' });
  };
  
  // Page change handler
  const handlePageChange = (newPage) => {
    setSearchParams({ search: query, page: newPage });
  };
  
  return (
    <div>
      <input 
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
        placeholder="Search..."
      />
      <p>Page: {page}</p>
      <button onClick={() => handlePageChange(String(Number(page) + 1))}>
        Next page
      </button>
    </div>
  );
}

Method 2: query-string (without router)

If you’re not using React Router, you can use the query-string library 📦

import { useState, useEffect } from 'react';
import queryString from 'query-string';
 
function SearchComponent() {
  // Parse current parameters from URL
  const parsed = queryString.parse(window.location.search);
  const [query, setQuery] = useState(parsed.search || '');
  
  // Update URL when query changes
  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="Search..."
      />
    </div>
  );
}

Method 3: Simple Custom Hook

You can create your own hook for working with URL parameters 🪝

import { useState, useCallback, useEffect } from 'react';
 
function useQueryParam(key) {
  // Function to get parameter value
  const getParam = useCallback(() => {
    const params = new URLSearchParams(window.location.search);
    return params.get(key) || '';
  }, [key]);
  
  // State to store the value
  const [value, setValue] = useState(getParam());
  
  // Function to update parameter
  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]);
  
  // Listen for URL changes
  useEffect(() => {
    const handlePopState = () => setValue(getParam());
    window.addEventListener('popstate', handlePopState);
    return () => window.removeEventListener('popstate', handlePopState);
  }, [getParam]);
  
  return [value, updateParam];
}
 
// Usage
function SearchComponent() {
  const [search, setSearch] = useQueryParam('search');
  
  return (
    <input 
      value={search}
      onChange={(e) => setSearch(e.target.value)}
      placeholder="Search..."
    />
  );
}

Useful Tips

1. Getting Multiple Parameters

// With React Router
const [searchParams] = useSearchParams();
 
// Get all parameters at once
const allParams = Object.fromEntries(searchParams.entries());
console.log(allParams); // { search: 'react', page: '1' }
 
// Check if parameter exists
const hasFilter = searchParams.has('filter');

2. Preserving Previous Parameters

const [searchParams, setSearchParams] = useSearchParams();
 
// Preserve existing parameters when updating
const updatePage = (newPage) => {
  const current = Object.fromEntries(searchParams.entries());
  setSearchParams({ ...current, page: newPage });
};

3. Tracking Parameter Changes

const [searchParams] = useSearchParams();
 
// Use useEffect to react to changes
useEffect(() => {
  const currentQuery = searchParams.get('search');
  // Perform search when query changes
  if (currentQuery) {
    fetchResults(currentQuery);
  }
}, [searchParams]); // Dependency on searchParams

Common Mistakes

Forgetting to Convert Types

// ❌ Mistake — parameters are always strings
const page = searchParams.get('page');
const nextPage = page + 1; // '11' instead of 2 if page='1'
 
// ✅ Correct — convert to number
const page = Number(searchParams.get('page') || '1');
const nextPage = page + 1; // 2 if page='1'

Not Handling Missing Parameters

// ❌ Mistake — parameter might be missing
const query = searchParams.get('search');
const firstLetter = query.charAt(0); // Error if query=null
 
// ✅ Correct — check existence
const query = searchParams.get('search') || '';
const firstLetter = query.charAt(0); // Safe

Simple Rules

  1. React Router — best choice for most projects 🥇
  2. URLSearchParams — built-in API for simple cases 🔧
  3. query-string — convenient library for complex cases 📚
  4. Always check if parameters exist before using them ✅
  5. Don’t forget about type conversion (string → number) 🔄
  6. Use useEffect to react to parameter changes 🔄

Understanding how to work with query parameters makes your React applications more functional and user-friendly! 💪


Want more articles to prepare for interviews? Subscribe to EasyAdvice, bookmark the site and improve yourself every day 💪