pmndrs / jotai

👻 Primitive and flexible state management for React
https://jotai.org
MIT License
18.72k stars 617 forks source link

feature request: add new atom function atomWithLocationQuery #1140

Closed ctrepka closed 2 years ago

ctrepka commented 2 years ago

Currently, atomWithHash permits the developer to listen to changes in the hash parameters of the URL with two-way data binding.

In my project, I am using the search/query params on the url, window.location.search. I would like to refrain from changing up the way the URL is parsed so that my current user-base can use the same url parameters as they always have (using the ? parameter instead of #).

Can we make this happen? It seems the changes are only a few lines of code from what is already implemented in atomWithHash, but this is blocking me from adopting Jotai for the application use-case I had in mind.

mattbdc commented 2 years ago

Sounds like a great idea for a community PR if "only a few lines of code" including tests.

However, it may be pushing into routing/navigation territory beyond whats comfortable for utils (idk), when you say blocking for your project - what is stopping you at this stage from using history listen and updating a primitive atom with the window.location.search https://github.com/remix-run/history/blob/dev/docs/getting-started.md - for the two way you should set the query in your setter function

dai-shi commented 2 years ago

As far as I understand, there's no standard way to allow two-way binding for window.location. That's why I made atomWithHash which we can use standard hashchange event.

I'd propose you to work on a new hook atomWithLocation instead of modifying atomWithHash. It will take subscribe as an option, which you can use both with react-router's history, or nextjs.

Related: https://github.com/pmndrs/jotai/issues/485#issuecomment-986247542

ctrepka commented 2 years ago

@mattbdc @dai-shi

All valid points and suggestions. My (perhaps naive) hope was that this was a common enough request that it was already in the works. Seems like that's not so, so I will work on implementing this in the future. I really like Jotai's simplicity next to Recoil (what I am using currently) and hope to switch soon.

I will have to come back to this when I have more time to explore Jotai and implement the hook myself, I just started playing around with it yesterday. I appreciate your time and suggestions!

JonParton commented 2 years ago

Just adding some love for this.

I was just checking out Jotai also coming from Recoil that now has nice RecoilSync functionality to sync to query params.

I much prefer query params for this sync over # (personal preference I know) but an atomWithLocation util would be awesome.

I'm not using Jotai at the moment so can't contribute but thought I'd make the desire from another potential user heard!

Note: Even when implementing recoil sync in a next.js app environment making sure changes fired whenever next changes things in the URL was a bit of a pain... especially with SSR involved (Basically had to subscribe on the router event and handle the server side instance) ... but the end result is awesome and easy to use after that initial setup energy. Especially as it is set up once in the provider not per atom.

dai-shi commented 2 years ago

I'd propose you to work on a new hook atomWithLocation

Well, because I learned about pushstate/popstate, here's my implementation. Please check out: https://github.com/jotai-labs/jotai-location (no docs. read the code. it's small.)

nerik commented 1 year ago

For anyone looking to transition from hash parameters to query params, here's a quick recipe:

const locationAtom = atomWithLocation();

const formerHashAtom = atom(
  (get) => get(locationAtom).searchParams?.get("hello"),
  (get, set, name) => {
    set(locationAtom, (prev) => ({
      ...prev,
      searchParams: new URLSearchParams([["hello", name as string]])
    }));
  }
);