Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass parameters to atom with async read function #68

Closed
fkocovski opened this issue Sep 25, 2020 · 4 comments
Closed

Pass parameters to atom with async read function #68

fkocovski opened this issue Sep 25, 2020 · 4 comments

Comments

@fkocovski
Copy link

First of all, amazing library, thank you so much :)

When I initialize an atom that will make an async call to an API endpoint, is there a way to pass an attribute? I know that I could write a primitive atom that will hold the parameter and make the async one dependent on it, but a more direct approach would be more elegant in my opinion.

I tried initializing it as follows but it keeps re-rendering my component infinitely and thus also makes infinite calls to the API

const fetchData =(id) atom({
   async ()=>{
      const res = await getDataByID(id)
      return res.data
   } 
})

Thanks for the support!

@dai-shi
Copy link
Member

dai-shi commented Sep 25, 2020

Hi,
It sounds to me that you would like to use write function, but I'm not quite sure. Please elaborate your use case, otherwise.

Here's an example with two atoms.

const emptyData = null
const dataAtom = atom(emptyData)
const fetchAtom = atom(
  get => get(dataAtom),
  async (_get, set, id) => set(dataAtom, (await getDataByID(id)).data)
)

This is not initialized unless it's explicitly used and invoked.

const [data, doFetch] = useAtom(fetchAtom)
useEffect(() => {
  doFetch(id)
}, [doFetch, id])

If you really want to avoid two atoms, you could do this:

const dataAtomWithFetch = atom(
  emptyData,
  async (_get, set, id) => set(dataAtomWithFetch, (await getDataByID(id)).data)
)

This is undocumented behavior. It's undocumented because we can't easily type it with TypeScript.

Hope it helps and look forward to hearing how it works or not.

@fkocovski
Copy link
Author

const [data, doFetch] = useAtom(fetchAtom)
useEffect(() => {
  doFetch(id)
}, [doFetch, id])

Thank you I just tried it and it actually works. Very straightforward logic :) Just a small clarification, are you referencing doFetch in the dependencies array of useEffect for performance reasons?

Again, thank you so much and I'm really looking forward to using Jotai even more!

@dai-shi
Copy link
Member

dai-shi commented Sep 25, 2020

are you referencing doFetch in the dependencies array of useEffect for performance reasons?

No, it's just because I know the exhaustive-deps rule complains otherwise.
Note doFetch returned by useAtom is wrapped by useCallback, so it's stable.

@fkocovski
Copy link
Author

No, it's just because I know the exhaustive-deps rule complains otherwise.

Great, I was hoping it was because of the warnings.

Note doFetch returned by useAtom is wrapped by useCallback, so it's stable.

Amazing 👍

Thank you once more for the help and keep up the terrific work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants