A powerful and lightweight React hook for managing filter state through URL search parameters. Seamlessly synchronize your application's filter state with the URL for better user experience and deep-linking support.
- 🔄 URL Synchronization - Automatically sync filter state with URL parameters
- 🌐 React Integration - Built specifically for React applications
- 📝 TypeScript Support - Full TypeScript support with type inference
- 🏷️ Namespacing - Support for multiple independent filter sets
- 💾 State Persistence - Filters persist through page refreshes
- 🎯 Zero Dependencies - Lightweight with no external dependencies
- 🔙 History Support - Seamless browser history integration
# Using npm
npm install react-filter-hook
# Using yarn
yarn add react-filter-hook
# Using pnpm
pnpm add react-filter-hook
import { useFilters } from 'react-filter-hook';
interface MyFilters {
search: string;
category: string;
minPrice: number;
maxPrice: number;
}
function ProductList() {
const { filters, onChangeFilter } = useFilters<MyFilters>({
namespace: 'products',
initialFilters: {
search: '',
category: 'all',
minPrice: 0,
maxPrice: 1000,
},
});
return (
<div>
<input
type='text'
value={filters.search}
onChange={(e) => onChangeFilter('search', e.target.value)}
placeholder='Search products...'
/>
<select
value={filters.category}
onChange={(e) => onChangeFilter('category', e.target.value)}
>
<option value='all'>All Categories</option>
<option value='electronics'>Electronics</option>
<option value='clothing'>Clothing</option>
</select>
<div>
<input
type='number'
value={filters.minPrice}
onChange={(e) => onChangeFilter('minPrice', Number(e.target.value))}
min={0}
max={filters.maxPrice}
/>
<input
type='number'
value={filters.maxPrice}
onChange={(e) => onChangeFilter('maxPrice', Number(e.target.value))}
min={filters.minPrice}
/>
</div>
</div>
);
}
The hook seamlessly handles array values, storing them as comma-separated values in the URL:
interface FiltersWithArrays {
tags: string[];
prices: number[];
}
const { filters, onChangeFilter } = useFilters<FiltersWithArrays>({
initialFilters: {
tags: [],
prices: [],
},
});
// Update array values
onChangeFilter('tags', ['react', 'typescript']);
// Results in URL: ?tags=react,typescript
The hook is fully typed and provides excellent TypeScript integration:
// Your filters will be fully typed
type MyFilters = {
category: 'all' | 'electronics' | 'clothing';
price: number;
inStock: boolean;
};
const { filters } = useFilters<MyFilters>({
initialFilters: {
category: 'all',
price: 0,
inStock: true,
},
});
// filters.category will only accept: 'all' | 'electronics' | 'clothing'
function useFilters<T>(options: FilterOptions<T>): {
filters: T;
onChangeFilter: (
key: keyof T,
value: T[keyof T],
options?: { resetSkip?: boolean }
) => void;
};
Option | Type | Required | Description |
---|---|---|---|
initialFilters | T |
Yes | The initial state of your filters |
namespace | string |
No | Prefix for URL parameters to avoid conflicts |
Property | Type | Description |
---|---|---|
filters | T |
Current state of the filters |
onChangeFilter | Function |
Function to update filter values |
import { useFilters } from 'react-filter-hook';
interface Filters {
search: string;
category: string;
minPrice: number;
maxPrice: number;
page: number;
}
function ProductList() {
const { filters, onChangeFilter } = useFilters<Filters>({
namespace: 'products',
initialFilters: {
search: '',
category: 'all',
minPrice: 0,
maxPrice: 1000,
page: 1,
},
});
// Use filters in your component
return (
<div>
<input
value={filters.search}
onChange={(e) => onChangeFilter('search', e.target.value)}
/>
{/* Other filter controls */}
</div>
);
}
// Filter set 1
const { filters: productFilters } = useFilters({
namespace: 'products',
initialFilters: {
/* ... */
},
});
// Filter set 2 (won't conflict with products)
const { filters: userFilters } = useFilters({
namespace: 'users',
initialFilters: {
/* ... */
},
});
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you find this package helpful, please consider:
- Starring the GitHub repository
- Creating an issue for any bugs or feature requests
- Contributing to the codebase