Spaces:
Running
Running
import { useSyncExternalStore } from "react"; | |
const subscribe = (callback: (searchParams: string) => void) => { | |
const listener = () => { | |
callback(window.location.search); | |
}; | |
window.addEventListener("popstate", listener); | |
return () => { | |
window.removeEventListener("popstate", listener); | |
}; | |
}; | |
const getSnapshot = () => { | |
return window.location.search; | |
}; | |
const getServerSnapshot = () => { | |
return window.location.search; | |
}; | |
const setSearchParams = (searchParams: Record<string, string>) => { | |
const url = new URL(window.location.href); | |
Object.entries(searchParams).forEach(([key, value]) => { | |
if (value === undefined || value === null || value === "") { | |
url.searchParams.delete(key); | |
} else { | |
url.searchParams.set(key, value); | |
} | |
}); | |
window.history.pushState({}, "", url); | |
window.dispatchEvent(new PopStateEvent("popstate")); | |
}; | |
export const useSearchParams = () => { | |
// using useSyncExternalStore to get the search params | |
// when the url changes, emit the new value and convert it to an object | |
// return an additional setter to update the search params with an object that is converted to a string and merged with the existing search params | |
const searchParams = useSyncExternalStore( | |
subscribe, | |
getSnapshot, | |
getServerSnapshot | |
); | |
return { | |
searchParams, | |
setSearchParams, | |
}; | |
}; | |