nitedani / zustand-querystring

A Zustand middleware that syncs the store with the querystring.
51 stars 6 forks source link

Query string formatting is odd? #1

Open chrisschwartzdev opened 1 year ago

chrisschwartzdev commented 1 year ago

My app has a very simple usage of this library where it stores the "search" query from a search box.

The store is set up like this:

const useShopStore = create<State>(
  querystring(
    (set) => ({
      query: "",
      items: undefined,
      fetchItems: async search => {
        set(() => ({ items: undefined, query: search?.query }))
        const inventory = await storeService.getItems(search);
        set(() => ({ items: inventory.items }))
      },
    }),
    {
      select(_: string) {
        return {
          query: true
        }
      }
    }))

It works, but the formatting of the query string in the address bar looks very odd. The resulting url is: http://localhost:3000/shop?$=query=some%20search%20query;;

I believe the proper formatting would be: http://localhost:3000/shop?query=some%20search%20query

Is this an error in the library or something that is configurable? Thanks in advance.

nitedani commented 1 year ago

This is by design. The readability and shortness of the generated querystring was important when I implemented this, but I also wanted to avoid breaking existing library/user code. The querystring middleware takes control of the addressbar of your browser and stores nested object structures in it serialized to a custom format. This format is not compatible with other libraries/user code. I wanted to minimize the number of issues/undefined behavior this would cause, for this reason the middleware stores all of the data in one single search parameter(by default $, this can be changed using the key prop). This way the middleware knows which part of the query string it has control over and it ignores the rest of it, so it wouldn't break existing code.

But you are right ideally the query string would look like your example. I will experiment with this and try to add a standalone: true setting, that would make it work like in your example.

chrisschwartzdev commented 1 year ago

Yeah that makes sense. I 100% approve of the idea to make it compatible with other libraries, but having the option to turn that off and use a cleaner format would be nice. Thanks!

mdwitr0 commented 1 year ago

Seconded, I too would like to see openapi formatted parameters so nextjs can work with them in server mode.

Right now I get them in this format :(

http://localhost:3001/popular?$=params$genres@=thriller&=detective;&countries@=Russia&=USA;;

next search params response:

 {
   '$': 'params$genres@=thriller',
   '': [ 'detective;', 'USA;;' ],
   'countries@': 'Russia'
 }
leoncvlt commented 10 months ago

+1 for the standalone argument, would be nice for the sake of a prettier / more human-readable URL in apps where this library is the only entity manipulating query params.

nitedani commented 9 months ago

http://localhost:3001/popular?$=params$genres@=thriller&=detective;&countries@=Russia&=USA;;

The parameters should be accessible from the store, on server-side. You can use the url option to provide the request url server-side. Then, the values will be set in the store, even server-side. https://github.com/nitedani/zustand-querystring/blob/main/examples/next/src/store.tsx

wingy3181 commented 9 months ago

Yep that worked on the server-side

Using the following

export default function ExampleRSCPage({ searchParams }: {
  searchParams?: { [key: string]: string | string[] | undefined };
}) {

  const store = createStore({ url: `?${new URLSearchParams(searchParams).toString()}` });

  const {
    count,
    ticks,
    someNestedState: { nestedCount, incrementNestedCount, hello, setHello },
  } = store.getState();

 return (
   <insert jsx using above)
)

Created a PR to show this as part of the examples https://github.com/nitedani/zustand-querystring/pull/7

nitedani commented 1 month ago

Released https://github.com/nitedani/zustand-querystring/releases/tag/v0.1.0 What do you think about the change?

ck-euan commented 1 month ago

@nitedani Is there a way to use the old readable style in the latest version?

nitedani commented 1 month ago

@ck-euan Not yet. I have an idea: making the encoding separate from the core logic, allowing users to provide their own encoder/decoder in the options. The library would also export the old encoder under zustand-querystring/encoding/urlon https://github.com/nitedani/zustand-querystring/issues/12