Skip to content

Instantly share code, notes, and snippets.

@SheryConcepts
Created October 1, 2023 16:04
Show Gist options
  • Save SheryConcepts/61582e8467657eb313b2a99aa0095ae9 to your computer and use it in GitHub Desktop.
Save SheryConcepts/61582e8467657eb313b2a99aa0095ae9 to your computer and use it in GitHub Desktop.
Utilities for handling search params in Nextjs applications.
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