1- import { usePathname , useRouter , useSearchParams } from "next/navigation " ;
1+ import { parseAsString , useQueryStates } from "nuqs " ;
22import { useEffect , useRef } from "react" ;
33import { selectFilters , setFilter } from "redux/filtersSlice" ;
44
@@ -7,13 +7,9 @@ import { Filters } from "../types";
77import { filterBarDropdown } from "../utils/constants" ;
88
99// Type for the keys of the Filters type
10- const queryFilter : ( keyof Filters ) [ ] = [
11- "capacity" ,
12- "usage" ,
13- "location" ,
14- "duration" ,
15- "id" ,
16- ] ;
10+ const filterQueries : ( keyof Filters ) [ ] = filterBarDropdown . map (
11+ ( { key } ) => key
12+ ) ;
1713
1814// Create an object that maps each filter key to its values in an array
1915const validFilterQueries : Partial < Record < keyof Filters , string [ ] > > =
@@ -24,43 +20,56 @@ const validFilterQueries: Partial<Record<keyof Filters, string[]>> =
2420 ] )
2521 ) ;
2622
23+ // Function to check if a given filter key and value are valid
2724const isValidFilter = ( key : keyof Filters , value : string ) : boolean => {
2825 const isValid = validFilterQueries [ key ] ;
29- if ( isValid === undefined ) return false ;
30- return isValid . includes ( value ) ;
26+ if ( isValid ) {
27+ return isValid . includes ( value ) ;
28+ }
29+ return false ;
3130} ;
3231
3332// Function to handle query string parameters for filters in page.tsx (browse page)
3433const useQueryFilter = ( ) => {
3534 const dispatch = useDispatch ( ) ;
36- const router = useRouter ( ) ;
37- const searchParams = useSearchParams ( ) ;
38- const pathname = usePathname ( ) ;
3935 const filters = useSelector ( selectFilters ) ;
4036
4137 // Only write to query parameters on initial load
4238 const initialLoad = useRef ( true ) ;
4339
44- // On initial load, apply filters from query parameters to Redux state
40+ const [ filterParams , setFilterParams ] = useQueryStates (
41+ {
42+ capacity : parseAsString . withDefault ( "" ) ,
43+ usage : parseAsString . withDefault ( "" ) ,
44+ location : parseAsString . withDefault ( "" ) ,
45+ duration : parseAsString . withDefault ( "" ) ,
46+ id : parseAsString . withDefault ( "" ) ,
47+ } ,
48+ { shallow : true }
49+ ) ;
50+
51+ // Apply filters from URL on load
4552 useEffect ( ( ) => {
46- const params = new URLSearchParams ( searchParams . toString ( ) ) ;
53+ const invalidKeys : Partial < Record < keyof Filters , null > > = { } ;
4754 let hasInvalidFilter = false ;
4855
49- queryFilter . forEach ( ( key ) => {
50- const value = searchParams . get ( key ) ;
51- if ( value && isValidFilter ( key , value ) ) {
52- dispatch ( setFilter ( { key, value } ) ) ;
53- } else {
54- params . delete ( key ) ;
55- hasInvalidFilter = true ;
56+ filterQueries . forEach ( ( key ) => {
57+ const value = filterParams [ key ] ;
58+ if ( value ) {
59+ if ( isValidFilter ( key , value ) ) {
60+ dispatch ( setFilter ( { key, value } ) ) ;
61+ } else {
62+ // Set as null to remove invalid filters
63+ invalidKeys [ key ] = null ;
64+ hasInvalidFilter = true ;
65+ }
5666 }
5767 } ) ;
5868
5969 // Check if need to update URL to remove invalid parameters
6070 if ( hasInvalidFilter ) {
61- router . replace ( ` ${ pathname } ? ${ params . toString ( ) } ` , { scroll : false } ) ;
71+ setFilterParams ( invalidKeys ) ;
6272 }
63-
6473 // eslint-disable-next-line react-hooks/exhaustive-deps
6574 } , [ dispatch ] ) ; // Apply filters on initial load (when user shares link with query params), and not on subsequent loads
6675
@@ -72,21 +81,15 @@ const useQueryFilter = () => {
7281 return ;
7382 }
7483
75- const params = new URLSearchParams ( searchParams . toString ( ) ) ;
76- queryFilter . forEach ( ( key ) => {
77- const value = filters [ key ] ;
78- if ( value && isValidFilter ( key , value ) ) {
79- // If the filter value exists and is a valid filter key, apply to query parameters
80- params . set ( key , value ) ;
81- } else {
82- // Remove the key if the filter value is not in the filter
83- params . delete ( key ) ;
84- }
84+ const params : Partial < Record < keyof Filters , string | null > > = { } ;
85+
86+ filterQueries . forEach ( ( key ) => {
87+ params [ key ] = filters [ key ] ?? null ;
8588 } ) ;
8689
87- // Update the URL with new query parameters
88- router . replace ( ` ${ pathname } ? ${ params . toString ( ) } ` , { scroll : false } ) ;
89- } , [ filters , pathname , router , searchParams ] ) ; // Update query parameters whenever filters change
90+ setFilterParams ( params ) ;
91+ // eslint-disable-next-line react-hooks/exhaustive-deps
92+ } , [ filters ] ) ;
9093} ;
9194
9295export default useQueryFilter ;
0 commit comments