import { create } from 'zustand'
import { persist } from 'zustand/middleware'
interface FilterState {
search: string
category: string | null
sortBy: 'recent' | 'popular' | 'oldest'
setSearch: (search: string) => void
setCategory: (category: string | null) => void
setSortBy: (sortBy: FilterState['sortBy']) => void
resetFilters: () => void
}
const initialState = {
search: '',
category: null,
sortBy: 'recent' as const,
}
export const useFilterStore = create<FilterState>()(
persist(
(set) => ({
...initialState,
setSearch: (search) => set({ search }),
setCategory: (category) => set({ category }),
setSortBy: (sortBy) => set({ sortBy }),
resetFilters: () => set(initialState),
}),
{
name: 'filter-storage',
}
)
)
import { useFilterStore } from '@/stores/useFilterStore'
export function PostFilters() {
const { search, category, sortBy, setSearch, setCategory, setSortBy, resetFilters } = useFilterStore()
return (
<div className="space-y-4 p-4 bg-white rounded-lg shadow">
<input
type="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
placeholder="Search posts..."
className="w-full px-3 py-2 border rounded"
/>
<select
value={category || ''}
onChange={(e) => setCategory(e.target.value || null)}
className="w-full px-3 py-2 border rounded"
>
<option value="">All Categories</option>
<option value="tech">Tech</option>
<option value="design">Design</option>
<option value="business">Business</option>
</select>
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value as FilterState['sortBy'])}
className="w-full px-3 py-2 border rounded"
>
<option value="recent">Most Recent</option>
<option value="popular">Most Popular</option>
<option value="oldest">Oldest First</option>
</select>
<button
onClick={resetFilters}
className="w-full px-3 py-2 bg-gray-200 rounded hover:bg-gray-300"
>
Reset Filters
</button>
</div>
)
}
Zustand provides a minimalist alternative to Redux with less boilerplate and better TypeScript support. I create stores with create that hold state and actions. Unlike Context, Zustand doesn't cause unnecessary re-renders—components only update when their selected state changes. Stores can be sliced into modules for better organization in large apps. Middleware like persist saves state to localStorage automatically. Zustand works great for client state that's too complex for useState but doesn't warrant Redux's ceremony. I use it for filters, UI preferences, or shopping carts. The devtools extension provides time-travel debugging similar to Redux. For most apps, Zustand hits the sweet spot between simplicity and power.