Closed22

AsyncなJotaiについて調べる

hajimismhajimism

まずは公式のど真ん中のページから
https://jotai.org/docs/guides/async

hajimismhajimism

ふつうにこれでSuspendするのか...つよいな

const asyncAtom = atom(async (get) => get(countAtom) * 2)

const [num] = useAtom(asyncAtom)
hajimismhajimism

derivedも可能

const anotherAtom = atom(async (get) => (await get(asyncAtom)) / 2)
hajimismhajimism

An interesting pattern that can be achieved with Jotai is switching from async to sync to trigger suspending when wanted.

初期値をstaticに入れておいて、必要に応じてdynamicな値を途中からいれるようなUIにすることもできると。

hajimismhajimism
hajimismhajimism

最初に<SomewhereX />がマウントされたとすると次に<SomewhereX />(or <SomewhereY />)をレンダリングする際はPromiseは解決されているのでfallbackは出ません。

そうか、Reactの外側でPromiseが解決されてるもんね

hajimismhajimism

atom familyでキャッシュ付きページネーション面白いな

// urlをキーとしてasync atomを作成
export const peopleFamily = atomFamily((url: string) =>
  atom(async () => {
    const {
      results: people,
      next: nextUrl,
      previous: previousUrl
    } = await fetchPeople(url);
    return { people, nextUrl, previousUrl };
  })
);
hajimismhajimism

revalidateTagみたいな

export const versionAtom = atom(0);
export const dataAtom = atom(async (get) => {
  get(version);
  const response = await fetch(...);
  return response.json();
});
hajimismhajimism

いやでもversionAtomの更新はhooksを通じてしか行えないからServer Actionsといっしょには使いづらいか

hajimismhajimism

ネットワーク処理をjotaiのコア機能のみで扱う場合、やりたいことが簡単にはできないことが出てきます。(出来ないことはないと思いますが自前で実装する必要が多いです)

Jotaiでデータフェッチ処理を扱いたい場合、”現時点では”、jotai/queryをおすすめします。RQのhooksで使うのではなく、です。

Tanstackいらなくなるかなと思ってたけど、そうでもないっぽい

hajimismhajimism

上記の問題を改善する為には、並列処理が必要です。並列にPromiseを解決する為には、utilsから提供されるwaitForAllが使えます。

Promise.all的な

hajimismhajimism

おすすめは、jotai-suspenseのusePrepareAtomsです。waitForAllを使ったシンプルなhooksとして提供されています。

こういうのちょっと苦手

hajimismhajimism

atom関数の第2引数がwrite関数です。write関数では何をやるにも自由なので、サイドエフェクトが許されます。

意識してなかったけどたしかに。

hajimismhajimism

あーこれいいな、面白いな

const paramsAtom = atom(...);
const postStatusAtom = atom({ requesting: false, error: null });
const asyncPostAtom = atom(
  (get) => get(postStatusAtom),
  async (get, set) => {
    set(postStatusAtom, { requesting: true, error: null });
    const result = await post(get(params));
    set(postStatusAtom, { requesting: false, error: result.error });
});

atomicに分かれてると読みやすいし、利用者側に併せてリッチなatomを合成することもできる。

hajimismhajimism

guideじゃないページもあるな
https://jotai.org/docs/utilities/async

hajimismhajimism

loadableよりも直接的に値にアクセスできるunwrap

const unwrapped1Atom = unwrap(delayedCountAtom)
// The value is `undefined` while pending

const unwrapped2Atom = unwrap(delayedCountAtom, (prev) => prev ?? 0)
// The value is `0` initially, and subsequent updates keep the previous value.
hajimismhajimism

そのままだと並列処理になってない点を除けば、Async Atomはかなり素朴に使えそう。

hajimismhajimism

ゆーてもこれはSuspendの設計の問題だから、Tanstackでもおきるか

When using React Query in suspense mode, this pattern of parallelism does not work, since the first query would throw a promise internally and would suspend the component before the other queries run. To get around this, you'll either need to use the useQueries hook (which is suggested) or orchestrate your own parallelism with separate components for each useQuery instance (which is lame).

https://tanstack.com/query/v4/docs/react/guides/parallel-queries

hajimismhajimism

TanstackのuseQueriesよりかは、jotai-suspenseのほうがSuspenseっぽいか。

hajimismhajimism

きちんとSuspense境界を定めれば大丈夫か?親の表示を早くできそうだけど並列にはならないか

このスクラップは2023/12/11にクローズされました