vuejs / apollo

🚀 Apollo/GraphQL integration for VueJS

Home Page:http://apollo.vuejs.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

useFragment

kevinvalk opened this issue · comments

Is your feature request related to a problem? Please describe.
I wanted to get a specific object from the cache that I knew would exist (because another query loading all objects of that type). Somehow graphQL (or useQuery) was not smart enough to resolve this object from cache via a normal useQuery. So I started reading the Apollo documentation and the useFragment hook they have https://www.apollographql.com/docs/react/api/react/hooks#usefragment sounded perfect! As in, just give me the data we have for a specific object.

Describe the solution you'd like
"Native" reactive useFragment method.

Describe alternatives you've considered
I ended up implementing a quick useFragment that gets the job done, but not more than that.

/**
 * Returns an always-up-to-date view of whatever data the cache currently contains for a given fragment and useFragment
 * never triggers network requests of its own.
 *
 * Based on https://www.apollographql.com/docs/react/api/react/hooks#usefragment code at https://github.com/apollographql/apollo-client/blob/a8fe0a1217d9784d3165e0ec2e88a2caca0f82d7/src/react/hooks/useFragment.ts#L1-L108
 * @param fragment
 * @param from
 * @param fragmentName
 */
export function useFragment<TResult = unknown, TVariables = unknown>(
  fragment: TypedDocumentNode<TResult, TVariables>,
  from: MaybeRefOrGetter<StoreObject | Reference | string | null | undefined>,
  fragmentName?: string
) {
  const { client } = useApolloClient();

  const data = shallowRef<TResult | undefined>(undefined);

  let unsubscribe: (() => void) | undefined = undefined;
  watchEffect(() => {
    const unwrappedFrom = toValue(from);

    // Remove our previous subscription
    if (unsubscribe !== undefined) {
      unsubscribe();
    }

    // If we have a from that is not "empty" we good!
    if (unwrappedFrom !== undefined && unwrappedFrom !== null) {
      unsubscribe = client.cache.watch<TResult, TVariables>({
        returnPartialData: true,
        immediate: true,
        id: typeof unwrappedFrom === 'string' ? unwrappedFrom : client.cache.identify(unwrappedFrom),
        // eslint-disable-next-line @typescript-eslint/dot-notation
        query: client.cache['getFragmentDoc'](fragment, fragmentName), // This is private, lol!
        optimistic: false,
        callback(diff) {
          // TODO: There is more to this I think: https://github.com/apollographql/apollo-client/blob/a8fe0a1217d9784d3165e0ec2e88a2caca0f82d7/src/react/hooks/useFragment.ts#L77-L82
          data.value = diff.result;
        },
      });
    }
  });

  return { data };
}

Additional context

commented

Does this feature exist in @apollo/client ?