JotaiJotai

状態
Primitive and flexible state management for React

waitForAll

Sometimes you have multiple async atoms in your components:

const dogsAtom = atom(async (get) => {
const response = await fetch('/dogs')
return await response.json()
})
const catsAtom = atom(async (get) => {
const response = await fetch('/cats')
return await response.json()
})
const App = () => {
const [dogs] = useAtom(dogsAtom)
const [cats] = useAtom(catsAtom)
// ...
}

However, this will start fetching one at the time, which is not optimal - It would be better if we can start fetching both as soon as possible.

The waitForAll utility is a concurrency helper, which allows us to evaluate multiple async atoms:

const dogsAtom = atom(async (get) => {
const response = await fetch('/dogs')
return await response.json()
})
const catsAtom = atom(async (get) => {
const response = await fetch('/cats')
return await response.json()
})
const App = () => {
const [[dogs, cats]] = useAtom(waitForAll([dogsAtom, catsAtom]))
// or ...
const [dogs, cats] = useAtomValue(waitForAll([dogsAtom, catsAtom]))
// ...
}

You can also use waitForAll inside an atom - It's also possible to name them for readability:

const dogsAtom = atom(async (get) => {
const response = await fetch('/dogs')
return await response.json()
})
const catsAtom = atom(async (get) => {
const response = await fetch('/cats')
return await response.json()
})
const animalsAtom = waitForAll({
dogs: dogsAtom,
cats: catsAtom,
})
const App = () => {
const [{ dogs, cats }] = useAtom(animalsAtom)
// or ...
const { dogs, cats } = useAtomValue(animalsAtom)
// ...
}

Note: If you use an object in waitForAll and waitForAll is inside render function, you need to wrap it with useMemo to avoid infinite loop.

Codesandbox