MDN URLSearchParams - discussion (2023-02-19)
URLSearchParams looks simple until you have to encode arrays, optional filters, and normalization rules (and then support asks why the same search link behaves differently). I like treating query serialization as a routing contract with explicit normalization and evidence lines.
Do you treat query params as a strict schema (validated/normalized) or do you pass them through loosely and tolerate weirdness? How do you serialize arrays and empty values so links are stable across clients? Do you render/log query normalization decisions so debugging doesn't require devtools?
Comments (12)
Back to latestStrict schema. If the URL is user-facing, it's part of the product contract.
We normalize and then re-serialize, so the URL becomes canonical.
We treat normalization as a first-class story:
txt
[tips] queryParse raw="?tag=react&tag=hooks" tags=[react,hooks]
[tips] queryNormalize tags sort=alpha result=[hooks,react]
[tips] querySerialize canonical="?tag=hooks&tag=react"
Once you do this, people stop arguing about why the URL changed because the reason is visible.
Concrete alternative: don't put everything in the URL. Put only the share-worthy posture in the URL and keep the rest local.
If you cram all filter state into query params, you create links nobody wants to share.
Agree. I think the key is being explicit about what is share-worthy.
If it's not part of the contract, it shouldn't be in the URL just because it's convenient.
Docs tie-in: query state is basically route state with a serialization layer.
Related: Routing and Navigation and State Management.
Long-form: URLSearchParams is great, but the hard part is defining invariants.
Do you allow duplicate keys? Do you sort? Do you drop empty values? Do you preserve unknown keys? Those decisions become user-facing behavior.
We wrote down the rules and logged them. Without that, every "why is this link different" bug turns into a week of archaeology.
We render a tiny evidence string like q:canon=1 when normalization occurred.
It prevents the subtle bug where the app keeps rewriting the URL and users think something is broken.
If you can, make canonical URLs idempotent: parsing and serializing should converge quickly.
If it doesn't converge, you built a URL oscillator.
Small detail: space encoding differences can cause surprising cache misses if your request key uses the raw URL.
Normalize before you compute request identity.
We also used URLSearchParams to create stable analytics event names (canonical query).
If you don't canonicalize, analytics is basically random.
If you expose query params, validate them and render evidence for invalid values (fallback happened).
Otherwise people share broken links and you can't tell what went wrong.
We keep unknown keys but we log them (so we can detect when old links are floating around).
It helped us during migrations because we could see what legacy parameters still mattered.
Takeaway: URLSearchParams is the easy part. Product rules are the hard part.
Write the rules down, log them, and your router stops feeling mysterious.