react-qif
Version:
Powerful filtering system for React.js applications
208 lines (168 loc) • 5.89 kB
Markdown
<div align="center">
<h1>🎯 Qif</h1>
<p><strong>Powerful filtering system for React.js applications</strong></p>
</div>
<div align="center">
[](https://www.npmjs.com/package/react-qif)
[](https://bundlephobia.com/result?p=react-qif@latest)
[](https://GitHub.com/hsnards/qif/contributors/)
[](https://github.com/hsnards/qif/blob/master/LICENSE)
[](https://github.com/hsnards/qif/compare)
</div>
## ✨ Features
- 🔄 **Centralized State System** - Efficient application state management
- 🎨 **Headless UI** - Flexible, unstyled components for full customization
- 🧩 **Composable Components** - Build complex UIs with simple, reusable parts
- 🔗 **URL Sync** - Built on nuqs for robust URL state management
- 🛠️ **Developer-Friendly API** - Intuitive design for seamless development
- ⚡ **Performance Optimized** - Smooth handling of large datasets
## 📦 Installation
```bash
# Using npm
npm install react-qif nuqs
# Using yarn
yarn add react-qif nuqs
```
## 🚀 Quick Start
```tsx
import { useFilters, FiltersProvider, useFiltersContext } from 'react-qif';
import { parseAsString } from 'nuqs';
type FiltersType = {
search: string;
category: string;
};
const App = () => {
const filtersInstance = useFilters({
parsers: {
search: parseAsString.withDefault(''),
category: parseAsString.withDefault('test')
}
});
return (
<FiltersProvider instance={filtersInstance}>
<SearchFilter />
</FiltersProvider>
);
};
const SearchFilter = () => {
const { getValue, setValue } = useFiltersContext<FiltersType>();
return (
<input
value={getValue('search') || ''}
onChange={(e) => setValue('search', e.target.value)}
/>
);
};
```
## 🔧 Setup
### 1. Configure NuqsAdapter
#### For Next.js:
```tsx
import { NuqsAdapter } from 'nuqs/adapters/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
<NuqsAdapter>{children}</NuqsAdapter>
</body>
</html>
);
}
```
#### For React:
```tsx
import { NuqsAdapter } from 'nuqs/adapters/react';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<NuqsAdapter>
<App />
</NuqsAdapter>
</StrictMode>
);
```
## 📚 API Reference
### FiltersProvider Props
- `instance`: Filter instance created by useFilters
- `children`: React nodes
### useFilters Hook Options
```tsx
interface UseFiltersOptions<T extends FiltersValue> {
syncWithSearchParams?: boolean;
parsers: UseQueryStatesKeysMap<T>;
}
```
### useFiltersContext Hook
Returns an object with the following methods:
- `register(name, defaultValue)`: Register a filter with default value
- `unregister(name)`: Remove a filter
- `setValue(name, value)`: Update filter value
- `getValue(name)`: Get current filter value
- `reset()`: Reset all filters to defaults
- `isResetDisabled`: Check if reset is available
## 🔄 Client-Side Filtering
Unlike nuqs, Qif also supports client-side filtering. By setting `syncWithSearchParams` to `false`, no parameters will be added to the URL. This is useful for temporary filters or when you don't want to persist the filter state in the URL.
### Client-Side Example
```tsx
const App = () => {
const filtersInstance = useFilters({
syncWithSearchParams: false, // Disable URL synchronization
parsers: {
search: parseAsString.withDefault(''),
category: parseAsString.withDefault('all')
}
});
return (
<FiltersProvider instance={filtersInstance}>
<ProductFilters />
<ProductList />
</FiltersProvider>
);
};
const ProductFilters = () => {
const { getValue, setValue } = useFiltersContext();
return (
<div className="filters">
<input
value={getValue('search') || ''}
onChange={(e) => setValue('search', e.target.value)}
placeholder="Search products..."
/>
<select
value={getValue('category') || 'all'}
onChange={(e) => setValue('category', e.target.value)}
>
<option value="all">All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
</select>
</div>
);
};
const ProductList = () => {
const { getValue } = useFiltersContext();
const searchTerm = getValue('search') as string;
const category = getValue('category') as string;
// Filter your products based on searchTerm and category
const filteredProducts = products.filter(product => {
const matchesSearch = product.name.toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory = category === 'all' || product.category === category;
return matchesSearch && matchesCategory;
});
return (
<div className="products">
{filteredProducts.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
};
```
This example demonstrates:
- Client-side filtering without URL parameter synchronization
- Multiple filter types (search input and category select)
- Real-time filtering of product list
- Type-safe filter values with TypeScript
## 🤝 Contributing
Contributions, issues and feature requests are welcome! Feel free to check [issues page](https://github.com/hsnards/qif/issues).
## 📄 License
MIT © [Hasan Ardestani](https://github.com/hsnards)