import { useStore, useWatch$, useClientEffect$, useServerMount$, } from "@builder.io/qwik"; export const ranAlready = new Set(); export function useUrlParams(initialState: STATE): STATE { const params = useStore(initialState); useWatch$((track) => { track(params); if (!ranAlready.has(params)) { // Skip first time - haven't had a chance to load the searchParams yet. ranAlready.add(params); return; } // put code to update `location.search` const url = new URL(window.location.href); for (const k in params) { url.searchParams.set(k, (params as any)[k]); } window.history.pushState({}, "", url); }); useClientEffect$(() => { const url = new URL(window.location.href); url.searchParams.forEach((v, k) => ((params as any)[k] = v)); // TODO listen to the `location.search` change, IF we want multiple // instances of this mechanism to act as an implicit communication channel }); useServerMount$(() => { // This part not tested yet because I don't have a working SSR setup with current mainline yet. const url = new URL(window.location.href); url.searchParams.forEach((v, k) => ((params as any)[k] = v)); }); return params; // TODO handle serializable non-strings in a way that roundtrips to the search // params and gets the same types back; perhaps borrow from: // https://github.com/pbeshai/use-query-params/blob/master/packages/serialize-query-params/src/serialize.ts }