I'd like to access the networkStatus property to know when a query is refetching. Currently loading only works for the initial load but not subsequent loads even with the notifyOnNetworkStatusChange option.
The way the createQuery function is implemented, it only exposes the data instead of the whole ApolloQueryResult. I ended up implementing my own createQuery that exposes the whole result object.
export const createQuery = <TData = {}, TVariables = OperationVariables>(
query: DocumentNode<TData, TVariables>,
options: CreateQueryOptions<TData, TVariables> = {},
) => {
const apolloClient = useApollo();
const optionsAccessor = () => {
if (typeof options !== 'function') {
if (options.skip) {
console.warn(
'you passed options.skip to createQuery, but the options are not an acccessor.\nThis query will never execute!\n\nReplace your options with a function.',
);
}
return options;
}
const opts = typeof options === 'function' ? options() : options;
if (opts.skip) {
return false;
}
return opts;
};
const [resource] = createResource<
ApolloQueryResult<TData>,
BaseOptions<TData, TVariables>
>(optionsAccessor, (opts) => {
const observable = apolloClient.watchQuery<TData, TVariables>({
query,
...opts,
});
const [state, setState] = createStore<ApolloQueryResult<TData>>({
data: undefined as any,
loading: true,
networkStatus: NetworkStatus.loading,
});
const sub = observable.subscribe({
error: (error) => {
setState(
reconcile({
loading: false,
networkStatus: NetworkStatus.error,
error,
data: undefined as any,
}),
);
},
next: (result) => {
setState(result);
},
});
onCleanup(() => sub.unsubscribe());
return state;
});
return resource;
};
This does mean I have to access resource()?.loading instead resource.loading and resource()?.data instead resource().
Are you interested in using something like this? Is there a better way to do it?
One immediate improvement would be figuring out how to make the resource always return a ApolloQueryResult<TData> instead of a ApolloQueryResult<TData> | undefined.
Another possible solution is to just use from to wrap watchQuery.
const createQuery = <TData, TVariables = OperationVariables>(
query: DocumentNode<TData, TVariables>,
options: CreateQueryOptions<TData, TVariables> = {},
) => {
const apolloClient = useApollo();
const optionsAccessor = () => {
if (typeof options !== 'function') {
if (options.skip) {
console.warn(
'you passed options.skip to createQuery, but the options are not an acccessor.\nThis query will never execute!\n\nReplace your options with a function.',
);
}
return options;
}
const opts = typeof options === 'function' ? options() : options;
if (opts.skip) {
// no skip possible with from?
return {};
}
return opts;
};
return from<ApolloQueryResult<TData>>((set) => {
const observable = apolloClient.watchQuery<TData, TVariables>({
query,
...optionsAccessor(),
});
const sub = observable.subscribe({
error: (error) => {
set(
reconcile({
loading: false,
networkStatus: NetworkStatus.error,
error,
data: undefined as any,
}),
);
},
next: (result) => {
set(result);
},
});
return () => sub.unsubscribe();
});
};
I'd like to access the
networkStatusproperty to know when a query is refetching. Currentlyloadingonly works for the initial load but not subsequent loads even with thenotifyOnNetworkStatusChangeoption.The way the
createQueryfunction is implemented, it only exposes thedatainstead of the wholeApolloQueryResult. I ended up implementing my owncreateQuerythat exposes the whole result object.This does mean I have to access
resource()?.loadinginsteadresource.loadingandresource()?.datainsteadresource().Are you interested in using something like this? Is there a better way to do it?
One immediate improvement would be figuring out how to make the resource always return a
ApolloQueryResult<TData>instead of aApolloQueryResult<TData> | undefined.Another possible solution is to just use
fromto wrapwatchQuery.