Skip to content

Supporting async getters inside atomWIthQuery #101

@peterpme

Description

@peterpme

Hi there,

I have an atomWithStorage that stores my user id that is then required to fetch user data:

const commentsAtom = atomWithQuery(async (get) => {
  const { id } = await get(userAtom); // b/c of atomWithStorage, this needs to be async 
  return queryCommentsQueryOptions ({ id })
});

Since atomWithQuery seems to dislike the async approach, we've created a new asyncAtomWithReactSuspenseQuery instead:

const commentsAtom = asyncAtomWithReactSuspenseQuery(async (get) => {
  const { id } = await get(userAtom);
  return queryCommentsQueryOptions ({ id })
});

This is what that implementation looks like. My question is: is there something I'm missing? I feel like I should be able to do this within the library itself so lmk if I've overlooked something. Thanks!

export const asyncAtomWithReactSuspenseQuery =
  makeWritableAsyncAtomWithTanstack(atomWithSuspenseQuery);
export const asyncAtomWithReactQuery =
  makeWritableAsyncAtomWithTanstack(atomWithQuery);

function makeWritableAsyncAtomWithTanstack<TOptions, TClient, TResult>(
  atomWithTanstack: (
    getOptions: (get: Getter) => TOptions,
    getQueryClient?: (get: Getter) => TClient
  ) => WritableAtom<TResult, [], void>
) {
  return (
    getOptions: (get: Getter) => Promise<TOptions>,
    getQueryClient?: (get: Getter) => Promise<TClient>
  ): WritableAtom<Promise<TResult>, [], void> => {
    const atomsAtom = atom<Promise<WritableAtom<TResult, [], void>>>(
      async (get) => {
        const [options, queryClient] = await Promise.all([
          getOptions(get),
          getQueryClient?.(get),
        ]);
        return atomWithTanstack(
          () => options,
          queryClient ? () => queryClient : undefined
        );
      }
    );
    return atom<Promise<TResult>, [], void>(
      async (get) => get(await get(atomsAtom)),
      async (get, set, ...args) => {
        const a = await get(atomsAtom);
        return set(a, ...args);
      }
    );
  };
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions