Skip to content

Latest commit

History

History
96 lines (75 loc) 路 2.38 KB

no-suspense.mdx

File metadata and controls

96 lines (75 loc) 路 2.38 KB
title nav
No Suspense
3.07

The content of this page will be easier to follow if you have taken a look at the basics/async part of the docs.

Sometimes we need to wrap our components in suspense to use asynchronous atoms.

But sometimes we're not allowed to wrap our components in Suspense, So we're going to do some hacks below and and make our async atoms synchronous.

Async read (Derived async atoms)

Check this derived async atom:

const urlAtom = atom('https://json.host.com')
const fetchUrlAtom = atom(async (get) => {
  const response = await fetch(get(urlAtom))
  return await response.json()
})

It needs Suspense because the read function returns a promise(async function).

We shouldn't return a promise if we don't need it to suspend, so we have to change the structure slightly.

Here's the new code.

const fetchResultAtom = atom({ loading: true, error: null, data: null })
const runFetchAtom = atom(
  (get) => get(fetchResultAtom),
  (_get, set, url) => {
    const fetchData = async () => {
      set(fetchResultAtom, (prev) => ({ ...prev, loading: true }))
      try {
        const response = await fetch(url)
        const data = await response.json()
        set(fetchResultAtom, { loading: false, error: null, data })
      } catch (error) {
        set(fetchResultAtom, { loading: false, error, data: null })
      }
    }
    fetchData()
  }
)
runFetchAtom.onMount = (runFetch) => {
  runFetch('https://json.host.com')
}

const Component = () => {
  const [result] = useAtom(runFetchAtom)

  console.log(result) // { loading: ..., error: ..., data: ... }
  return <div>...</div>
}
For async write until v1.3.9

(This is no longer the case since v1.4.0.)

Async write (Asynchronous actions)

The original code is:

const fetchCountAtom = atom(
  (get) => get(countAtom),
  async (_get, set, url) => {
    const response = await fetch(url)
    set(countAtom, (await response.json()).count)
  }
)

The write function (2nd arg) returns a promise, which will suspend.

We just need to make it synchronous and returns nothing, just like this:

const fetchCountAtom = atom(
  (get) => get(countAtom),
  (_get, set, url) => {
    const fetchData = async () => {
      const response = await fetch(url)
      set(countAtom, (await response.json()).count)
    }
    fetchData()
  }
)