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
Does this feature exist in @apollo/client ?
Does this feature exist in @apollo/client ?
Yes, see: https://www.apollographql.com/docs/react/api/react/hooks/#usefragment (@apollo/client 3.8.0+)
And source code: https://github.com/apollographql/apollo-client/blob/a8fe0a1217d9784d3165e0ec2e88a2caca0f82d7/src/react/hooks/useFragment.ts#L44-L92