Not a member yet? Read this story for free here
When building interactive web applications, filters are a critical feature that allow users to narrow down data to what's most relevant to them. However, how you manage the state of these filters critically impacts the user experience. A common approach is to use React's useState
hook or global state management solutions like Redux or Context API to store filter values. While these methods work, they come with certain limitations, especially when it comes to sharing filtered views.
In this blog, we will discuss why storing filter states in the URL is a better approach and how we can easily implement this using React Router. By doing so, we'll optimize the filter feature in our application, making it more reliable and user-friendly.
The Importance of Filter State Management
Filters help users navigate large datasets by refining the results based on specific criteria. For instance, in an e-commerce application, users might filter products by category, price, or brand. If the filter state is managed poorly, users may face several frustrations, such as losing their filter settings when navigating away from the page or being unable to share a specific filtered view with others.
General Approach
In the general approach to managing filter state in React, we typically use the useState
hook to store the selected filter option and the filtered data. This method allows for real-time updates of the UI based on the user's selection.
In the code below, the filter
state determines whether "All," "Fruits," or "Vegetables" are displayed, and the q
state captures the search query entered by the user. The useEffect
hook is used to update the filtered data whenever the filter state or search query changes. This approach is straightforward and effective for simple filtering and search needs, though it may not offer the persistence or shareability benefits of more advanced methods, such as storing filter states in the URL.
Why useState and Global State Fall Short
Using the useState
hook or global state management solutions like Redux or Context API to manage filter states is a common practice. However, these approaches have significant drawbacks:
- Loss of Data on Navigation: Imagine a user applies several filters to find a specific set of results. If they accidentally click a link to another page and then use the browser's back button, all their filter settings will be lost. This can be extremely frustrating, especially for complex filtering scenarios.
- Inability to Share Filtered Views: When filter states are stored in
useState
, Redux, or Context API, there's no way to capture and share a specific filtered view via a URL. This limits the usability of the filter feature, particularly in scenarios where users need to collaborate or revisit a specific filtered dataset. - Limited Persistency Across Sessions: While global state solutions like Redux or Context API allow for state management across components, they do not inherently provide a way to persist state across sessions. If a user refreshes the page or returns later, the filter state may be lost unless additional measures are taken.
The Better Approach: Store Filters in the URL
Storing filter states in the URL not only addresses these issues but also significantly enhances the user experience by ensuring persistence and shareability. The following image shows a sample of filters stored in the URL, which helps to persist the filter state, share URLs with the required filters, and improve user experience.

Storing filters in the URL makes implementation straightforward, especially with React Router. Let's explore how to implement this.
Step 1: Replace useState with useSearchParams
Start by replacing the useState
hook with the useSearchParams
hook from React Router. This hook allows us to manage URL query parameters as if they were state variables.
Like React's own useState
hook, useSearchParams
returns an array of two values: the current location's search params and a function that may be used to update them.
import { useSearchParams } from 'react-router-dom';
const [searchParams, setSearchParams] = useSearchParams();
const q = searchParams.get('q') || '';
const filter = searchParams.get('filter');
Step 2: Update URL Parameters on Filter Change
When the filter input changes, update the URL parameters using setSearchParams
. This ensures that the current filter state is always reflected in the URL.
const handleSearchChange = (e) => {
setSearchParams(prevParams => {
const newParams = new URLSearchParams(prevParams);
newParams.set('q', e.target.value);
return newParams;
});
};
const handleFilterChange = (value) => {
setSearchParams(prevParams => {
const newParams = new URLSearchParams(prevParams);
newParams.set('filter', value);
return newParams;
});
};
Step 3: Prevent Back Button Issues
One downside to this approach is that each filter change creates a new history entry, which might cause unexpected behavior when using the browser's back button. To avoid this, we can replace the current URL entry instead of pushing a new one:
setSearchParams(newParams, { replace: true });
Here is the modified complete code that effectively addresses the problem discussed earlier, along with the optimized solution:
Storing filter states in the URL, rather than useState
, ensures persistent filters across navigation, allows for shareable filtered views via URLs, and provides a more seamless and reliable user experience. With React Router's useSearchParams
hook, this can be implemented quickly and effectively, making our React applications more robust and user-friendly.
I hope you found this guide helpful! I'd love to hear your thoughts or any challenges you've faced with filter state management. Feel free to share in the comments below!
Follow me on:
GitHub: https://github.com/tanmaythole
LinkedIn: https://www.linkedin.com/in/tanmaythole/
Thanks for reading, and happy coding! 👨🏽💻
In Plain English 🚀
Thank you for being a part of the In Plain English community! Before you go:
- Be sure to clap and follow the writer ️👏️️
- Follow us: X | LinkedIn | YouTube | Discord | Newsletter
- Visit our other platforms: CoFeed | Differ
- More content at PlainEnglish.io