TanStackT
TanStack5mo ago
41 replies
radical-lime

Custom Search Param Serialization

Hi, I’m running into an issue with search param serialization in TanStack Router. When I pass arrays into search, the URL looks like this:
https://example.com/route?country=%5B%22DNK%22%2C%22FIN%22%5D


That’s the array JSON-encoded into a single query param value. What I’d like instead is the more standard repeated-keys format:
https://example.com/route?country=DNK&country=FIN&page=2


I tried following the docs with query-string:

const router = createRouter({
  stringifySearch: stringifySearchWith((value) =>
    qs.stringify(value),
  ),
  parseSearch: parseSearchWith((value) =>
    qs.parse(value),
  ),
})


I'm using zod to validate search params in my routes:

const schema = z.object({
  country: z.array(z.string()).optional(),
})


But the problem is that the value passed into stringifySearchWith isn’t an array. Instead I’m seeing objects with only number–value pairs like
{0: "DNK", 1: "FIN"}
. That means they end up in the URL as
?country=0%3DFIN
. I don’t even have access to the original key.

This break my validation logic where array is expected:

Something went wrong!

[
  {
    "expected": "array",
    "code": "invalid_type",
    "path": [
      "country"
    ],
    "message": "Invalid input: expected array, received object"
  }
]


What’s the recommended way in TanStack Router to produce repeated query keys (?country=DNK&country=FIN) and parse them back into arrays for search params? Any help here would be appreciated 🙏
Was this page helpful?