Learn how to build instant, responsive product filters in React with clean URL search parameters state synchronization.
When building online stores, developers often store filter choices like category, price range, and color inside React's local useState hook. While this works initially, it creates poor user experiences. When a user reloads the page, shares the URL with a friend, or clicks the browser back button, all their filter choices disappear because the URL did not change.
In projects like [Shopease / Oud & Attar](/projects/2), keeping URL search parameters in sync with filter selections solved this issue entirely. Users can bookmark exact search criteria or share URLs that open the catalog with the exact same filters applied.
To synchronize filter state with the URL without causing unnecessary re-renders or sluggish page navigation, we can use React Router's useSearchParams hook or native browser APIs. Here is a production-tested pattern for managing multi-faceted filters cleanly.
import { useSearchParams } from 'react-router-dom';
import { useCallback } from 'react';
interface FilterState {
category: string;
minPrice: number;
maxPrice: number;
inStock: boolean;
}
export function useProductFilters() {
const [searchParams, setSearchParams] = useSearchParams();
const filters: FilterState = {
category: searchParams.get('category') || 'all',
minPrice: Number(searchParams.get('minPrice')) || 0,
maxPrice: Number(searchParams.get('maxPrice')) || 10000,
inStock: searchParams.get('inStock') === 'true',
};
const setFilter = useCallback(
(key: keyof FilterState, value: string | number | boolean) => {
const newParams = new URLSearchParams(searchParams);
if (value === 'all' || value === 0 || value === false) {
newParams.delete(key);
} else {
newParams.set(key, String(value));
}
setSearchParams(newParams, { replace: true });
},
[searchParams, setSearchParams]
);
return { filters, setFilter };
}
To keep product filtering snappy and responsive, follow these practical guidelines during development:
As an independent web developer, I build fast, production-ready web applications, e-commerce stores, and custom software. Explore my [Full-Stack Web Development Services](/services) or [get in touch with Aafaque](/contact) to discuss your project.
Storing filters in URL query parameters ensures that user selections persist on page refresh, makes browser back and forward buttons work correctly, and allows users to share direct links to filtered product lists.
You can prevent lag by keeping filter calculations on the client side for small to medium product catalogs, using React's useTransition hook to keep the interface responsive, and debouncing text search inputs.
Client-side filtering is extremely fast for catalogs up to a few thousand items, running in milliseconds. For catalogs with tens of thousands of items, filtering should happen on the server, while the URL still holds the parameters.