useProductFilters
unknown
typescript
a year ago
1.8 kB
7
Indexable
import { usePathname, useRouter } from "next/navigation" import { useCallback, useEffect, useMemo, useState } from "react" interface ProductFilters { search: string | null category: string | null rating: [number, number] | null maxPrice: number | null } type FilterKey = keyof ProductFilters type FilterValue = string | number | [number, number] | null const initFilters: ProductFilters = { search: null, category: null, rating: null, maxPrice: null, } const parseFilterValue = (value: FilterValue): string | null => { if (value === null) { return null } if (typeof value === "string") { return value } if (typeof value === "number") { return value.toString() } if ( Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number" ) { return `${value[0]} - ${value[1]}` } return null } export default function useProductFilters() { const router = useRouter() const pathname = usePathname() const [filters, setFilters] = useState<ProductFilters>(initFilters) const params = useMemo(() => { const params = new URLSearchParams() for (const key of Object.keys(filters)) { const value = parseFilterValue(filters[key as FilterKey]) if (!!value) { params.set(key, value) } else { params.delete(key) } } return params }, [filters]) const setFilter = <K extends FilterKey>( key: K, value: ProductFilters[K] ): void => { setFilters((filters) => ({ ...filters, [key]: value })) } const getFilter = useCallback( <K extends FilterKey>(key: K): ProductFilters[K] => { return filters[key] }, [filters] ) return { setFilter, getFilter } }
Editor is loading...
Leave a Comment