Skip to content

Commit e7d0bbb

Browse files
authored
ref(tsc): Convert Discover homepage to FC + useApiQuery (#87519)
1 parent e71ea19 commit e7d0bbb

File tree

3 files changed

+71
-79
lines changed

3 files changed

+71
-79
lines changed

static/app/views/discover/homepage.spec.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,11 @@ describe('Discover > Homepage', () => {
277277
{router: initialData.router, organization: initialData.organization}
278278
);
279279

280-
expect(mockHomepage).toHaveBeenCalled();
281-
expect(screen.getByRole('button', {name: /set as default/i})).toBeDisabled();
282280
await waitFor(() => {
283-
expect(measurementsMetaMock).toHaveBeenCalled();
281+
expect(screen.getByRole('button', {name: /set as default/i})).toBeDisabled();
284282
});
283+
284+
expect(measurementsMetaMock).toHaveBeenCalled();
285285
});
286286

287287
it('follows absolute date selection', async () => {

static/app/views/discover/homepage.tsx

+65-73
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
import {useEffect} from 'react';
12
import type {Location} from 'history';
23

34
import type {Client} from 'sentry/api';
4-
import DeprecatedAsyncComponent from 'sentry/components/deprecatedAsyncComponent';
5+
import LoadingError from 'sentry/components/loadingError';
6+
import LoadingIndicator from 'sentry/components/loadingIndicator';
57
import PageFiltersContainer from 'sentry/components/organizations/pageFilters/container';
68
import {
79
getDatetimeFromState,
@@ -11,8 +13,12 @@ import {getPageFilterStorage} from 'sentry/components/organizations/pageFilters/
1113
import type {PageFilters} from 'sentry/types/core';
1214
import type {InjectedRouter} from 'sentry/types/legacyReactRouter';
1315
import type {Organization, SavedQuery} from 'sentry/types/organization';
14-
import {browserHistory} from 'sentry/utils/browserHistory';
1516
import EventView from 'sentry/utils/discover/eventView';
17+
import {type ApiQueryKey, useApiQuery, useQueryClient} from 'sentry/utils/queryClient';
18+
import {useLocation} from 'sentry/utils/useLocation';
19+
import {useNavigate} from 'sentry/utils/useNavigate';
20+
import useOrganization from 'sentry/utils/useOrganization';
21+
import usePrevious from 'sentry/utils/usePrevious';
1622
import withApi from 'sentry/utils/withApi';
1723
import withOrganization from 'sentry/utils/withOrganization';
1824
import withPageFilters from 'sentry/utils/withPageFilters';
@@ -30,27 +36,42 @@ type Props = {
3036
setSavedQuery: (savedQuery: SavedQuery) => void;
3137
};
3238

33-
type HomepageQueryState = DeprecatedAsyncComponent['state'] & {
34-
savedQuery?: SavedQuery | null;
35-
starfishResult?: null;
36-
};
39+
function makeDiscoverHomepageQueryKey(organization: Organization): ApiQueryKey {
40+
return [`/organizations/${organization.slug}/discover/homepage/`];
41+
}
3742

38-
class HomepageQueryAPI extends DeprecatedAsyncComponent<Props, HomepageQueryState> {
39-
shouldReload = true;
43+
function Homepage(props: Props) {
44+
const organization = useOrganization();
45+
const queryClient = useQueryClient();
46+
const location = useLocation();
47+
const navigate = useNavigate();
48+
const {data, isLoading, isError, refetch} = useApiQuery<SavedQuery>(
49+
makeDiscoverHomepageQueryKey(organization),
50+
{
51+
staleTime: 0,
52+
enabled: organization.features.includes('discover-query'),
53+
}
54+
);
4055

41-
componentDidUpdate(_: any, prevState: any) {
42-
const hasFetchedSavedQuery = !prevState.savedQuery && this.state.savedQuery;
43-
const hasInitiallyLoaded = prevState.loading && !this.state.loading;
44-
const sidebarClicked = this.state.savedQuery && this.props.location.search === '';
45-
const hasValidEventViewInURL = EventView.fromLocation(this.props.location).isValid();
56+
const savedQuery = organization.features.includes(
57+
'performance-discover-dataset-selector'
58+
)
59+
? getSavedQueryWithDataset(data)
60+
: data;
61+
62+
const previousSavedQuery = usePrevious(savedQuery);
63+
64+
useEffect(() => {
65+
const hasFetchedSavedQuery = !previousSavedQuery && savedQuery;
66+
const sidebarClicked = savedQuery && location.search === '';
67+
const hasValidEventViewInURL = EventView.fromLocation(location).isValid();
4668

4769
if (
48-
this.state.savedQuery &&
49-
((hasInitiallyLoaded && hasFetchedSavedQuery && !hasValidEventViewInURL) ||
50-
sidebarClicked)
70+
savedQuery &&
71+
((hasFetchedSavedQuery && !hasValidEventViewInURL) || sidebarClicked)
5172
) {
52-
const eventView = EventView.fromSavedQuery(this.state.savedQuery);
53-
const pageFilterState = getPageFilterStorage(this.props.organization.slug);
73+
const eventView = EventView.fromSavedQuery(savedQuery);
74+
const pageFilterState = getPageFilterStorage(organization.slug);
5475
let query = {
5576
...eventView.generateQueryStringObject(),
5677
};
@@ -79,75 +100,46 @@ class HomepageQueryAPI extends DeprecatedAsyncComponent<Props, HomepageQueryStat
79100
});
80101
}
81102

82-
browserHistory.replace({
83-
...this.props.location,
84-
query: {
85-
...query,
86-
queryDataset: this.state.savedQuery?.queryDataset,
103+
navigate(
104+
{
105+
...location,
106+
query: {
107+
...query,
108+
queryDataset: savedQuery?.queryDataset,
109+
},
87110
},
88-
});
111+
{replace: true}
112+
);
89113
}
90-
}
114+
}, [savedQuery, location, previousSavedQuery, navigate, organization.slug]);
91115

92-
getEndpoints(): ReturnType<DeprecatedAsyncComponent['getEndpoints']> {
93-
const {organization} = this.props;
94-
95-
const endpoints: ReturnType<DeprecatedAsyncComponent['getEndpoints']> = [];
96-
if (organization.features.includes('discover-query')) {
97-
endpoints.push([
98-
'savedQuery',
99-
`/organizations/${organization.slug}/discover/homepage/`,
100-
]);
101-
}
102-
return endpoints;
116+
if (isLoading) {
117+
return <LoadingIndicator />;
103118
}
104119

105-
onRequestSuccess({stateKey, data}: any) {
106-
const {organization} = this.props;
107-
// No homepage query results in a 204, returning an empty string
108-
if (stateKey === 'savedQuery' && data === '') {
109-
this.setState({savedQuery: null});
110-
return;
111-
}
112-
if (stateKey === 'savedQuery') {
113-
this.setState({
114-
savedQuery: organization.features.includes(
115-
'performance-discover-dataset-selector'
116-
)
117-
? getSavedQueryWithDataset(data)
118-
: data,
119-
});
120-
}
120+
if (isError) {
121+
return <LoadingError onRetry={refetch} />;
121122
}
122123

123-
setSavedQuery = (newSavedQuery?: SavedQuery) => {
124-
const {organization} = this.props;
125-
this.setState({
126-
savedQuery: organization.features.includes('performance-discover-dataset-selector')
127-
? (getSavedQueryWithDataset(newSavedQuery) as SavedQuery)
128-
: newSavedQuery,
129-
});
124+
const setSavedQuery = (newSavedQuery?: SavedQuery) => {
125+
queryClient.setQueryData(makeDiscoverHomepageQueryKey(organization), newSavedQuery);
130126
};
131127

132-
renderBody(): React.ReactNode {
133-
const {savedQuery, loading} = this.state;
134-
135-
return (
136-
<Results
137-
{...this.props}
138-
savedQuery={savedQuery ?? undefined}
139-
loading={loading}
140-
setSavedQuery={this.setSavedQuery}
141-
isHomepage
142-
/>
143-
);
144-
}
128+
return (
129+
<Results
130+
{...props}
131+
savedQuery={savedQuery}
132+
loading={isLoading}
133+
setSavedQuery={setSavedQuery}
134+
isHomepage
135+
/>
136+
);
145137
}
146138

147139
function HomepageContainer(props: Props) {
148140
return (
149141
<PageFiltersContainer skipInitializeUrlParams>
150-
<HomepageQueryAPI {...props} />
142+
<Homepage {...props} />
151143
</PageFiltersContainer>
152144
);
153145
}

static/app/views/discover/savedQuery/utils.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@ export function getSavedQueryDataset(
282282
return SavedQueryDatasets.DISCOVER;
283283
}
284284

285-
export function getSavedQueryWithDataset(
286-
savedQuery?: SavedQuery | NewQuery
287-
): SavedQuery | NewQuery | undefined {
285+
export function getSavedQueryWithDataset<T extends SavedQuery | NewQuery>(
286+
savedQuery?: T
287+
): T | undefined {
288288
if (!savedQuery) {
289289
return undefined;
290290
}

0 commit comments

Comments
 (0)