queryClient.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import * as reactQuery from '@tanstack/react-query';
  2. import {QueryClientConfig} from '@tanstack/react-query';
  3. import RequestError from 'sentry/utils/requestError/requestError';
  4. import useApi from 'sentry/utils/useApi';
  5. type QueryKeyEndpointOptions = {
  6. query?: Record<string, any>;
  7. };
  8. type QueryKey =
  9. | readonly [url: string]
  10. | readonly [url: string, options: QueryKeyEndpointOptions];
  11. type UseQueryOptions<TQueryFnData, TError = RequestError, TData = TQueryFnData> = Omit<
  12. reactQuery.UseQueryOptions<TQueryFnData, TError, TData, QueryKey>,
  13. 'queryKey' | 'queryFn'
  14. >;
  15. // We are not overriding any defaults options for stale time, retries, etc.
  16. // See https://tanstack.com/query/v4/docs/guides/important-defaults
  17. const DEFAULT_QUERY_CLIENT_CONFIG: QueryClientConfig = {};
  18. function isQueryFn<TQueryFnData, TError, TData>(
  19. queryFnOrQueryOptions?:
  20. | reactQuery.QueryFunction<TQueryFnData, QueryKey>
  21. | UseQueryOptions<TQueryFnData, TError, TData>
  22. ): queryFnOrQueryOptions is reactQuery.QueryFunction<TQueryFnData, QueryKey> {
  23. return typeof queryFnOrQueryOptions === 'function';
  24. }
  25. /**
  26. * Wraps React Query's useQuery for consistent usage in the Sentry app.
  27. * Query keys should be an array which include an endpoint URL and options such as query params.
  28. * This wrapper will execute the request using the query key URL, but if you need custom behavior
  29. * you may supply your own query function as the second argument.
  30. *
  31. * See https://tanstack.com/query/v4/docs/overview for docs on React Query.
  32. *
  33. * Example usage:
  34. *
  35. * const { data, isLoading, isError } = useQuery<EventsResponse>(['/events', { query: { limit: 50 }}])
  36. */
  37. function useQuery<TQueryFnData, TError = RequestError, TData = TQueryFnData>(
  38. queryKey: QueryKey,
  39. queryOptions?: UseQueryOptions<TQueryFnData, TError, TData>
  40. ): reactQuery.UseQueryResult<TData, TError>;
  41. /**
  42. * Example usage with custom query function:
  43. *
  44. * const { data, isLoading, isError } = useQuery<EventsResponse>(['events'], () => api.requestPromise(...))
  45. */
  46. function useQuery<TQueryFnData, TError = RequestError, TData = TQueryFnData>(
  47. queryKey: QueryKey,
  48. queryFn?: reactQuery.QueryFunction<TQueryFnData, QueryKey>,
  49. queryOptions?: UseQueryOptions<TQueryFnData, TError, TData>
  50. ): reactQuery.UseQueryResult<TData, TError>;
  51. function useQuery<TQueryFnData, TError = RequestError, TData = TQueryFnData>(
  52. queryKey: QueryKey,
  53. queryFnOrQueryOptions?:
  54. | reactQuery.QueryFunction<TQueryFnData, QueryKey>
  55. | UseQueryOptions<TQueryFnData, TError, TData>,
  56. queryOptions?: UseQueryOptions<TQueryFnData, TError, TData>
  57. ): reactQuery.UseQueryResult<TData, TError> {
  58. const api = useApi();
  59. const [path, endpointOptions] = queryKey;
  60. const defaultQueryFn: reactQuery.QueryFunction<TQueryFnData, QueryKey> = () =>
  61. api.requestPromise(path, {
  62. method: 'GET',
  63. query: endpointOptions?.query,
  64. });
  65. const queryFn = isQueryFn(queryFnOrQueryOptions)
  66. ? queryFnOrQueryOptions
  67. : defaultQueryFn;
  68. const options =
  69. queryOptions ??
  70. (isQueryFn(queryFnOrQueryOptions) ? undefined : queryFnOrQueryOptions);
  71. return reactQuery.useQuery(queryKey, queryFn, options);
  72. }
  73. // eslint-disable-next-line import/export
  74. export * from '@tanstack/react-query';
  75. // eslint-disable-next-line import/export
  76. export {DEFAULT_QUERY_CLIENT_CONFIG, useQuery, UseQueryOptions};