# How to Use React Router useSearchParams to Manage Query Parameters in v6

> Learn to use React Router v6 useSearchParams to effortlessly read and update URL query parameters. Manage your app's state with this powerful hook. No full page reloads needed.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: how-to-guide
- Published: 2026-02-20

---

**React Router v6's `useSearchParams` hook returns a tuple containing a `URLSearchParams` instance and a setter function, enabling components to read and update URL query parameters without triggering full page reloads.**

While examining the `facebook/react` repository, it is essential to recognize that routing functionality resides in the separate **React Router** ecosystem. The `useSearchParams` hook, distributed via the `react-router-dom` package, provides a synchronized interface to the browser's query string, allowing React components to consume and modify URL state declaratively. This implementation leverages React Router's internal navigation context to ensure UI components re-render whenever search parameters change.

## Understanding the useSearchParams API

The `useSearchParams` hook follows a pattern similar to React's `useState`, but specifically for URL search parameters. When invoked inside a component rendered within a Router, it returns:

```ts
const [searchParams, setSearchParams] = useSearchParams();

```

The `searchParams` object is an **immutable** `URLSearchParams` instance reflecting the current `location.search` value. The `setSearchParams` function accepts three types of arguments:

1. A new `URLSearchParams` object
2. A plain JavaScript object containing key-value pairs
3. A function that receives the current `URLSearchParams` and returns a new one

By default, calling `setSearchParams` pushes a new entry onto the browser's history stack. You can alter this behavior by passing `{ replace: true }` as a second argument, which replaces the current history entry instead.

## Reading Query Parameters with useSearchParams

To access individual values from the query string, use the standard `URLSearchParams` methods on the returned object. The most common method is `get()`, which retrieves the first value associated with a given key.

```tsx
import { useSearchParams } from "react-router-dom";

function ProductFilter() {
  const [searchParams] = useSearchParams();
  
  // Read specific parameters with fallback values
  const category = searchParams.get("category") ?? "all";
  const sortOrder = searchParams.get("sort") ?? "ascending";
  const page = parseInt(searchParams.get("page") ?? "1", 10);

  return (
    <div>
      <p>Current Category: {category}</p>
      <p>Sort: {sortOrder}</p>
      <p>Page: {page}</p>
    </div>
  );
}

```

For boolean-like parameters, check for existence using `has()`, or handle multiple values with `getAll()` when the same key appears multiple times in the query string.

## Updating URL Search Parameters

### Replacing All Parameters

To completely reset the query string, pass a plain object or new `URLSearchParams` instance to the setter. This removes any existing parameters not included in the new object.

```tsx
const [searchParams, setSearchParams] = useSearchParams();

// Clear all filters and set only category
const setCategoryOnly = (newCategory: string) => {
  setSearchParams({ category: newCategory });
};

```

### Modifying Specific Parameters

Typically, you want to update one parameter while preserving others. Create a mutable copy of the current `searchParams` using the constructor, then modify it.

```tsx
const updateFilter = (key: string, value: string) => {
  const nextParams = new URLSearchParams(searchParams);
  nextParams.set(key, value);
  setSearchParams(nextParams);
};

```

### Functional Updates

When the new state depends on the previous state, pass a function to `setSearchParams`. This ensures you operate on the most current parameters, avoiding stale closure issues in rapid update scenarios.

```tsx
const incrementPage = () => {
  setSearchParams((prev) => {
    const currentPage = parseInt(prev.get("page") ?? "1", 10);
    prev.set("page", String(currentPage + 1));
    return prev;
  });
};

```

### Using Replace vs Push

Prevent polluting the browser history when updating transient UI state (like search filters) by using the `replace` option.

```tsx
// Replace current history entry instead of pushing new one
setSearchParams({ search: query }, { replace: true });

```

According to the React Router source code in [`packages/react-router-dom/index.tsx`](https://github.com/facebook/react/blob/main/packages/react-router-dom/index.tsx), the `setSearchParams` implementation wraps the `useNavigate` hook to perform these history mutations, while [`packages/react-router/dom.ts`](https://github.com/facebook/react/blob/main/packages/react-router/dom.ts) contains the underlying navigation logic that handles the `replace` flag.

## Complete Working Example

The following component demonstrates reading, updating, and clearing query parameters in a product listing interface:

```tsx
import { useSearchParams } from "react-router-dom";

function ProductList() {
  // 1️⃣ Obtain the current query parameters and the setter
  const [searchParams, setSearchParams] = useSearchParams();

  // 2️⃣ Read a specific parameter (e.g., ?category=books)
  const category = searchParams.get("category") ?? "all";

  // 3️⃣ Update a parameter while preserving the others
  const changeCategory = (newCat: string) => {
    // Create a copy, modify it, then push the new URL
    const next = new URLSearchParams(searchParams);
    next.set("category", newCat);
    setSearchParams(next);
  };

  // 4️⃣ Remove a parameter (e.g., clearing a filter)
  const clearSearch = () => {
    // Passing an empty object removes all query params
    setSearchParams({});
  };

  return (
    <div>
      <h2>Products – Category: {category}</h2>

      {/* Buttons to demonstrate updates */}
      <button onClick={() => changeCategory("books")}>Books</button>
      <button onClick={() => changeCategory("electronics")}>Electronics</button>
      <button onClick={clearSearch}>Clear Filters</button>

      {/* Render filtered product list based on `category` … */}
    </div>
  );
}

```

## Implementation Architecture

Although you are examining the `facebook/react` repository, the `useSearchParams` implementation resides in the **React Router** codebase at `remix-run/react-router`. The hook is defined in [`packages/react-router-dom/index.tsx`](https://github.com/facebook/react/blob/main/packages/react-router-dom/index.tsx), where it composes `useNavigate` and `useLocation` from the core router packages. The actual history manipulation relies on the navigation logic in [`packages/react-router/dom.ts`](https://github.com/facebook/react/blob/main/packages/react-router/dom.ts), while the location state management derives from [`packages/react-router/history.ts`](https://github.com/facebook/react/blob/main/packages/react-router/history.ts). This architecture ensures that any parameter changes flow through React Router's centralized history management, triggering re-renders only for components subscribed to the relevant route context.

## Summary

- **`useSearchParams`** returns a tuple of `[URLSearchParams, setter]` for reading and writing query parameters in React Router v6 applications.
- The **setter function** accepts objects, `URLSearchParams` instances, or functional updates, providing flexibility for different state management patterns.
- Always **create a copy** of `searchParams` before mutating to preserve existing query parameters when updating individual values.
- Use the **`{ replace: true }`** option to update the URL without creating new browser history entries for transient state changes.
- The implementation lives in the `react-router-dom` package, specifically utilizing logic from [`packages/react-router-dom/index.tsx`](https://github.com/facebook/react/blob/main/packages/react-router-dom/index.tsx) and [`packages/react-router/dom.ts`](https://github.com/facebook/react/blob/main/packages/react-router/dom.ts).

## Frequently Asked Questions

### How do I access multiple values for the same query parameter key?

Use the `getAll()` method on the `searchParams` object returned by `useSearchParams`. For example, if your URL contains `?tag=react&tag=router`, calling `searchParams.getAll("tag")` returns an array `["react", "router"]`. This is useful for handling multi-select filters or arrays encoded in the query string.

### Can I use useSearchParams outside of a Router component?

No. The `useSearchParams` hook relies on React Router's navigation context, which is provided by `BrowserRouter`, `HashRouter`, or `MemoryRouter`. Attempting to use the hook outside of any Router provider will throw a context error. Ensure your component tree is wrapped in a Router component from `react-router-dom` before calling this hook.

### What is the difference between useSearchParams and the native URLSearchParams API?

While `useSearchParams` returns a standard `URLSearchParams` instance for reading, its setter function (`setSearchParams`) is React Router's abstraction over the browser's history API. Unlike manual `window.location.search` updates, `setSearchParams` integrates with React Router's routing system, triggering component re-renders and respecting the router's basename or future configuration options defined in [`packages/react-router/history.ts`](https://github.com/facebook/react/blob/main/packages/react-router/history.ts).

### How do I remove a specific query parameter while keeping others?

Create a new `URLSearchParams` instance from the current one, call the `delete()` method on the specific key, then pass the modified object to `setSearchParams`. For example: `const next = new URLSearchParams(searchParams); next.delete("filter"); setSearchParams(next);`. This preserves all other query parameters intact.