React Forum
Blog & Guide Responses
Jan 12, 2023 · 04:00 AM

MDN URLSearchParams - discussion (2023-01-12)

Started by Talia Moss
externalmdnurlsearchparamsroutingquery paramsroute truth

I keep coming back to URLSearchParams when teams want to put *everything* into the URL and then discover the URL is not actually a state model. MDN explains the primitive well; I'm curious how people decide what becomes query params, what becomes route state, and what stays local document truth.

Read the MDN docs

What do you keep in query params vs in route state (especially for filters and sort)? How do you avoid parsing/serializing params in five places and getting drift? Do you treat URL params as the source of truth, or as a hint that seeds route state once?

Comments (16)

Back to latest
Camille Duarte
Jan 16, 2023 · 04:30 PM

We treat query params as a hint: read once, write route truth, then re-serialize for sharing.

If you treat the URL as the only truth, you end up with parsing code everywhere.

Marisol Vega
Jan 27, 2023 · 09:04 AM

A small but useful convention: one module owns parsing/serialization and returns a typed object.

Then components only deal in the typed shape, not in strings.

Dmitri Kline
Feb 09, 2023 · 09:10 PM

We have a helper that normalizes params so you don't accidentally treat missing keys differently across panels:

ts
export type Filters = { q: string; sort: 'new' | 'top'; page: number };

export function parseFilters(search: string): Filters {
  const p = new URLSearchParams(search);
  const q = p.get('q') ?? '';
  const sort = (p.get('sort') as Filters['sort']) ?? 'new';
  const page = Number(p.get('page') ?? '1');
  return { q, sort, page: Number.isFinite(page) ? page : 1 };
}
Keira Santos
Feb 24, 2023 · 04:41 AM

Counterpoint: treating URL as hint can make deep links feel "soft" if route state diverges after initial seed.

We had to be careful to re-serialize route truth back into the URL so sharing still worked.

Talia Moss
Feb 27, 2023 · 06:03 PM

Yep, the hint approach only works if you have a consistent re-serialization step.

Otherwise you get the worst of both worlds: URL isn't truth, but also doesn't reflect truth.

Grace McCoy
Mar 10, 2023 · 11:12 AM

For filters/sort, we keep them in route state because back/forward should replay them predictably.

The URL gets a short set of keys so sharing works, but the route contract is the real model.

Jasper Nguyen
Mar 29, 2023 · 06:20 AM

We used to encode arrays in query params (e.g. tag=a&tag=b) and it got messy quickly.

Now we normalize arrays into a stable string so ordering doesn't cause cache differences.

Nina Kapoor
Apr 18, 2023 · 11:17 PM

MDN's doc is also a good reminder: URLSearchParams is not a router.

If you start using it as a router, you end up inventing navigation intent in string manipulation.

Benji Rios
May 08, 2023 · 02:02 PM

We render query/filters as evidence in the shell (data-q, data-sort, data-page).

If you do that, you can stop guessing whether the URL parse worked.

Amina Farouk
Jun 15, 2023 · 10:48 AM

Docs tie-in: the routing posture in this repo is basically "URL gives where; state gives what".

Related: Routing and Navigation and The App Router Mindset.

Owen Price
Aug 01, 2023 · 04:09 AM

We had a bug where two panels serialized sort differently (recent vs newest) and it broke sharing links.

Central parsing/serialization is worth it just to avoid that class of bug.

Lina Ortega
Oct 10, 2023 · 09:50 PM

Counterpoint: if you don't put filters in the URL, users can't share the view they meant.

We ended up putting the keys users care about in the URL and keeping the rest route-only.

Theo Bennett
Dec 02, 2023 · 03:15 PM

URLSearchParams is simple, but the design question isn't. The model matters more than the syntax.

Priya Liao
Feb 21, 2024 · 08:36 AM

One thing MDN doesn't cover: if you build cache keys from query strings, normalization is essential.

Different ordering of params can create surprising duplicate cache entries.

Tomas Rivera
May 14, 2024 · 07:20 PM

If you want to keep URL handling boring, write a module and never call new URLSearchParams() in components.

It's the easiest style rule we added and it paid off immediately.

Evan Brooks
Aug 28, 2024 · 04:50 AM

We also store a derived shareUrl string as evidence so users can copy the exact canonical link for the current route posture.

It sounds redundant, but it prevents subtle drift between what's shown and what's shared.

Salma Qureshi
Nov 09, 2024 · 12:03 PM

This is a good example of why the forum patterns emphasize evidence.

If you can see the route truth in the DOM, URL parsing bugs aren't mysterious anymore.