releasesProvider.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import {createContext, useContext, useEffect, useState} from 'react';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import {Client} from 'sentry/api';
  4. import {t} from 'sentry/locale';
  5. import {Organization, PageFilters, Release} from 'sentry/types';
  6. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  7. import useApi from '../useApi';
  8. function fetchReleases(api: Client, orgSlug: string, selection: PageFilters) {
  9. const {environments, projects} = selection;
  10. return api.requestPromise(`/organizations/${orgSlug}/releases/`, {
  11. method: 'GET',
  12. data: {
  13. sort: 'date',
  14. project: projects,
  15. per_page: 50,
  16. environment: environments,
  17. },
  18. });
  19. }
  20. type ReleasesProviderProps = {
  21. children: React.ReactNode;
  22. organization: Organization;
  23. selection: PageFilters;
  24. skipLoad?: boolean;
  25. };
  26. function ReleasesProvider({
  27. children,
  28. organization,
  29. selection,
  30. skipLoad = false,
  31. }: ReleasesProviderProps) {
  32. const api = useApi();
  33. const [releases, setReleases] = useState<Release[]>([]);
  34. const [loading, setLoading] = useState(true);
  35. useEffect(() => {
  36. if (skipLoad) {
  37. setLoading(false);
  38. return undefined;
  39. }
  40. let shouldCancelRequest = false;
  41. setLoading(true);
  42. fetchReleases(api, organization.slug, selection)
  43. .then(response => {
  44. if (shouldCancelRequest) {
  45. setLoading(false);
  46. return;
  47. }
  48. setLoading(false);
  49. setReleases(response);
  50. })
  51. .catch(e => {
  52. if (shouldCancelRequest) {
  53. setLoading(false);
  54. return;
  55. }
  56. const errorResponse = e?.responseJSON ?? t('Unable to fetch releases');
  57. addErrorMessage(errorResponse);
  58. setLoading(false);
  59. handleXhrErrorResponse(errorResponse)(e);
  60. });
  61. return () => {
  62. shouldCancelRequest = true;
  63. };
  64. // eslint-disable-next-line react-hooks/exhaustive-deps
  65. }, [skipLoad, api, organization.slug, JSON.stringify(selection)]);
  66. return (
  67. <ReleasesContext.Provider value={{releases, loading}}>
  68. {children}
  69. </ReleasesContext.Provider>
  70. );
  71. }
  72. interface ReleasesContextValue {
  73. loading: boolean;
  74. releases: Release[];
  75. }
  76. const ReleasesContext = createContext<ReleasesContextValue | undefined>(undefined);
  77. function useReleases() {
  78. const releasesContext = useContext(ReleasesContext);
  79. if (!releasesContext) {
  80. throw new Error('releasesContext was called outside of ReleasesProvider');
  81. }
  82. return releasesContext;
  83. }
  84. const ReleasesConsumer = ReleasesContext.Consumer;
  85. export {ReleasesContext, ReleasesConsumer, ReleasesProvider, useReleases};