SearchParams cannot distinguish between an array of 1 and a single primitive value
I'm not entirely sure if I misconfigured something or if the docs are outdated now, but according to https://tanstack.com/router/v1/docs/guide/search-params#json-first-search-params, JSON is supported in search parameters and is encoded into something like:
/shop?pageIndex=3&includeCategories=%5B%22electronics%22%2C%22gifts%22%5D&sortBy=price&desc=true
However in a sandbox I'm using to test this functionality, I'm noticing that arrays are represented as key=firstValue&key=secondValue. Calling useSearch() against this results in { key: ['firstValue', 'secondValue'] }.
The issue is that if you set an array of 1, the url is in the same format as if you didn't use an array at all, thus calling useSearch results in { key: 'firstValue' } instead of { key: ['firstValue']}.
This occurs using both: router.navigate({ key: ['firstValue'] }) and <Link search={{ key: ['firstValue'] }} />
Here is a code sandbox if that helps: https://codesandbox.io/s/tanstack-array-in-search-params-issue-c3nzt3?file=/src/App.js13 Replies
other-emerald•3y ago
Ooo you’re right
I’ll fix this when I get back in front of my computer.
File and issue.
conscious-sapphireOP•3y ago
GitHub
SearchParameters no longer encoded as JSON · Issue #711 · TanStack/...
Describe the bug Discussed on Discord According to https://tanstack.com/router/v1/docs/guide/search-params#json-first-search-params, JSON is supported in search parameters and is encoded into somet...
conscious-sapphireOP•3y ago
A related follow up question: Do you have any plans on supporting an integration like
query-string? It would be nice to be able to choose between key[]=first&key=[]second vs key=.
I'm aware there is a "Custom Search Param Serialization" page, but it seems to only apply for seralization a value to a specific key, and doesn't allow you to customize how the entirety of the search object is formatted.other-emerald•3y ago
I believe you can alter that as well. But I may be wrong.
Router.options.parseSearch and stringifySearxh should work.
conscious-sapphireOP•3y ago
unfortunately the documentation doesn't really state what
parseSearch by itself is used for (the link to it is 404), but when used in conjunction with parseSearchWith, it only allows you to modify the single value. I also noticed that if you were passing an array into navigate({search: value}), it never even calls parseSearch somehow 😅 I sorta asssumed your intention was for parseSearch to only work with primitives.
let me do a little more digging and I can put together a better example for you
nevermind I take it back! I looked into the source code to see what parseSearch does and figured it out. It works great with query-string. Thanks for your help!other-emerald•3y ago
Yep!
If you can figure out how to change the default to handle this use case, I will accept a PR
conscious-sapphireOP•3y ago
I think the way you have it is fine, though I think the documentation can be improved a little. I'll type something up and open a PR for you.
conscious-sapphireOP•3y ago
https://github.com/TanStack/router/pull/712
I didn't know if you were cool with having a reference to a separate library (
query-string) but I couldn't come up with an example for parseSearch and stringifySearch that didn't require writing a bunch of custom serialization code. I figured most people would probably be trying to do something like I was doing, so I just put my example in there.GitHub
docs: Add example for parseSearch and stringifySearch by sowhatdoid...
Added an example on how to use parseSearch and stringifySearch without the parseSearchWith and stringifySearchWith utilities.
conscious-sapphireOP•3y ago
open to making any changes that you suggest though
other-emerald•3y ago
I think we need to fix the single array item turning into a string issue.
conscious-sapphireOP•3y ago
ohh sorry, I thought you were going to look into that yourself and the pull request suggestion was for the parseSearch stuff
So it seems like the problem is with the encode function in ./qss
Based on your commit message, you're using a copy of https://www.npmjs.com/package/qss, which based on their examples the behavior we're seeing is expected. From what I can gather, this package doesn't support arrays of 1, and does not support nested objects.
I modified the code so that it would properly match your old encoding for arrays, but I think this is going to become a thread pull to ensure nested objects as well.
I'm not sure what your opinion on how the url should be structured by default is.
If you're trying to base it out of the URLSearchParams standard, it doesn't support any of the above either: no nested objects, no arrays, and no differentiation between strings and numbers.
if you want it to be a little more robust, you may want to consider switching from qss to a different library. As I mentioned I was using query-string, which admittedly is slower than QSS by a lot, but I'm not knowledgeable enough to know what the impact of those benchmark results would be on your product.
I'm happy to work on a solution if you can give a little guidance direction wise
other-emerald•3y ago
Fixed the default
Happy to consider another one as long as it’s similar in size.
conscious-sapphireOP•3y ago
thank you!