Created
October 1, 2023 16:04
-
-
Save SheryConcepts/61582e8467657eb313b2a99aa0095ae9 to your computer and use it in GitHub Desktop.
Utilities for handling search params in Nextjs applications.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback, useEffect, useState, useTransition } from "react"; | |
import { usePathname, useSearchParams } from "next/navigation"; | |
import { useRouter } from "next/navigation"; | |
export function debounced<T extends (...args: any[]) => any>( | |
func: T, | |
duration: number, | |
): (...args: Parameters<T>) => ReturnType<T> { | |
let timeoutId: NodeJS.Timeout; | |
let result: ReturnType<T>; | |
return (...args: Parameters<T>) => { | |
timeoutId && clearTimeout(timeoutId); | |
timeoutId = setTimeout(() => { | |
result = func(...args); | |
}, duration); | |
return result; | |
}; | |
} | |
export function useSetSearchParams(): [ | |
string, | |
(params: { | |
[name: string]: (string | number) | Array<string | number>; | |
}) => void, | |
] { | |
const pathname = usePathname(); | |
const searchParams = useSearchParams(); | |
const [params, setParams] = useState(() => { | |
return pathname + "?" + searchParams.toString(); | |
}); | |
const createQueryString = useCallback( | |
(name: string, value: (string | number) | Array<string | number>) => { | |
const params = new URLSearchParams(searchParams); | |
if (value instanceof Array) { | |
params.set(name, value.join(",")); | |
return params.toString(); | |
} | |
params.set(name, typeof value === "number" ? value.toString() : value); | |
return params.toString(); | |
}, | |
[searchParams], | |
); | |
return [ | |
params, | |
(paramsObject: { | |
[name: string]: (string | number) | Array<string | number>; | |
}) => { | |
for (let i in paramsObject) { | |
console.log(paramsObject); | |
const newParams = createQueryString(i, paramsObject[i]); | |
const path = pathname + "?" + newParams; | |
setParams(path); | |
} | |
}, | |
]; | |
} | |
export function usePushSeachParams(): [ | |
string, | |
(params: { | |
[name: string]: (string | number) | Array<string | number>; | |
}) => void, | |
boolean, | |
] { | |
const pathname = usePathname(); | |
const searchParams = useSearchParams(); | |
const [params, setParams] = useState(() => { | |
return pathname + "?" + searchParams.toString(); | |
}); | |
const router = useRouter(); | |
const [pending, startTransition] = useTransition(); | |
const createQueryString = useCallback( | |
(name: string, value: (string | number) | Array<string | number>) => { | |
const params = new URLSearchParams(searchParams); | |
if (value instanceof Array) { | |
params.set(name, value.join(",")); | |
return params.toString(); | |
} | |
params.set(name, typeof value === "number" ? value.toString() : value); | |
return params.toString(); | |
}, | |
[searchParams], | |
); | |
// push route i.e transition only after waiting 500 ms, to avoid extra requests to server | |
const pushRoute = useCallback( | |
debounced((route: string) => { | |
startTransition(() => { | |
router.push(route); | |
}); | |
}, 500), | |
[], | |
); | |
useEffect(() => { | |
pushRoute(params); | |
}, [params]); | |
return [ | |
params, | |
(paramsObject: { | |
[name: string]: (string | number) | Array<string | number>; | |
}) => { | |
for (let i in paramsObject) { | |
console.log(paramsObject); | |
const newParams = createQueryString(i, paramsObject[i]); | |
const path = pathname + "?" + newParams; | |
setParams(path); | |
} | |
}, | |
pending, | |
]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment