Skip to content

Commit 13bf47c

Browse files
committed
feat: add abortController for plugin list
1 parent 0226315 commit 13bf47c

File tree

4 files changed

+54
-26
lines changed

4 files changed

+54
-26
lines changed

src/Shared/Components/Plugin/PluginList.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import PluginCard from './PluginCard'
44
import { DetectBottom } from '../DetectBottom'
55
import PluginCardSkeletonList from './PluginCardSkeletonList'
66
import { PluginListParamsType, PluginListProps } from './types'
7-
import { GenericEmptyState, GenericFilterEmptyState, showError } from '../../../Common'
7+
import {
8+
abortPreviousRequests,
9+
GenericEmptyState,
10+
GenericFilterEmptyState,
11+
getIsRequestAborted,
12+
showError,
13+
} from '../../../Common'
814
import { getPluginStoreData } from './service'
915

1016
const PluginList = ({
@@ -18,23 +24,31 @@ const PluginList = ({
1824
isSelectable,
1925
handleClearFilters,
2026
showCardBorder,
27+
getPluginStoreRef,
2128
}: PluginListProps) => {
2229
const { appId } = useParams<PluginListParamsType>()
2330

2431
const [isLoadingMorePlugins, setIsLoadingMorePlugins] = useState<boolean>(false)
2532
const handleLoadMore = async () => {
2633
setIsLoadingMorePlugins(true)
2734
try {
28-
const pluginDataResponse = await getPluginStoreData({
29-
searchKey,
30-
offset: pluginList.length,
31-
selectedTags,
32-
appId: appId ? +appId : null,
33-
})
35+
const pluginDataResponse = await abortPreviousRequests(
36+
() =>
37+
getPluginStoreData({
38+
searchKey,
39+
offset: pluginList.length,
40+
selectedTags,
41+
appId: appId ? +appId : null,
42+
signal: getPluginStoreRef.current.signal,
43+
}),
44+
getPluginStoreRef,
45+
)
3446

3547
handleDataUpdateForPluginResponse(pluginDataResponse, true)
3648
} catch (error) {
37-
showError(error)
49+
if (!getIsRequestAborted(error)) {
50+
showError(error)
51+
}
3852
} finally {
3953
setIsLoadingMorePlugins(false)
4054
}

src/Shared/Components/Plugin/PluginListContainer.tsx

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { useEffect, useState } from 'react'
1+
import { useEffect, useRef, useState } from 'react'
22
import { useParams } from 'react-router'
33
import { APIResponseHandler } from '../APIResponseHandler'
44
import PluginTagSelect from './PluginTagSelect'
55
import PluginList from './PluginList'
66
import { FilterChips } from '../FilterChips'
77
import PluginCardSkeletonList from './PluginCardSkeletonList'
8-
import { SearchBar, useAsync } from '../../../Common'
8+
import { abortPreviousRequests, getIsRequestAborted, SearchBar, useAsync } from '../../../Common'
99
import { getAvailablePluginTags, getPluginStoreData } from './service'
1010
import {
1111
PluginListParamsType,
@@ -44,6 +44,7 @@ const PluginListContainer = ({
4444
const [filters, setFilters] = useState<PluginListFiltersType>(
4545
parentFilters || structuredClone(DEFAULT_PLUGIN_LIST_FILTERS),
4646
)
47+
const abortControllerRef: PluginListProps['getPluginStoreRef'] = useRef(new AbortController())
4748

4849
const handlePluginListUpdate = (updatedPluginList: PluginListItemType[]) => {
4950
setPluginList(updatedPluginList)
@@ -62,16 +63,21 @@ const PluginListContainer = ({
6263

6364
const { searchKey, selectedTags } = filters || {}
6465

65-
// TODO: Add abortController as well
66+
const getPluginStoreDataWrapper = () =>
67+
abortPreviousRequests(
68+
() =>
69+
getPluginStoreData({
70+
searchKey,
71+
selectedTags,
72+
offset: 0,
73+
appId: appId ? +appId : null,
74+
signal: abortControllerRef.current.signal,
75+
}),
76+
abortControllerRef,
77+
)
78+
6679
const [isLoadingPluginData, pluginData, pluginDataError, reloadPluginData] = useAsync(
67-
() =>
68-
getPluginStoreData({
69-
searchKey,
70-
selectedTags,
71-
offset: 0,
72-
appId: appId ? +appId : null,
73-
}),
74-
// TODO: Test if this is correct since new reference is created every time
80+
getPluginStoreDataWrapper,
7581
persistFilters ? [pluginList] : [searchKey, appId, selectedTags],
7682
persistFilters ? !pluginList.length : true,
7783
)
@@ -135,8 +141,9 @@ const PluginListContainer = ({
135141
}
136142

137143
useEffect(() => {
144+
const isLoading = isLoadingPluginData || getIsRequestAborted(pluginDataError)
138145
// This will be reusable for load more so convert it to a function
139-
if (!isLoadingPluginData && !pluginDataError && pluginData) {
146+
if (!isLoading && !pluginDataError && pluginData) {
140147
handleDataUpdateForPluginResponse(pluginData)
141148
}
142149
}, [isLoadingPluginData, pluginData, pluginDataError])
@@ -225,7 +232,7 @@ const PluginListContainer = ({
225232
)}
226233

227234
<APIResponseHandler
228-
isLoading={isLoadingPluginData}
235+
isLoading={isLoadingPluginData || getIsRequestAborted(pluginDataError)}
229236
customLoader={<PluginCardSkeletonList count={5} />}
230237
error={pluginDataError}
231238
errorScreenManagerProps={{
@@ -244,6 +251,7 @@ const PluginListContainer = ({
244251
isSelectable={isSelectable}
245252
handleClearFilters={handleClearFilters}
246253
showCardBorder={showCardBorder}
254+
getPluginStoreRef={abortControllerRef}
247255
/>
248256
</APIResponseHandler>
249257
</div>

src/Shared/Components/Plugin/service.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { get, getUrlWithSearchParams, ResponseType, ROUTES, showError } from '../../../Common'
1+
import { get, getIsRequestAborted, getUrlWithSearchParams, ResponseType, ROUTES, showError } from '../../../Common'
22
import { stringComparatorBySortOrder } from '../../Helpers'
33
import {
44
GetPluginListPayloadType,
@@ -44,6 +44,7 @@ export const getPluginStoreData = async ({
4444
selectedTags,
4545
appId,
4646
offset = 0,
47+
signal,
4748
}: GetPluginStoreDataServiceParamsType): Promise<GetPluginStoreDataReturnType> => {
4849
try {
4950
const payload: GetPluginListPayloadType = {
@@ -53,17 +54,19 @@ export const getPluginStoreData = async ({
5354
size: 20,
5455
tag: selectedTags,
5556
}
56-
const { result } = (await get(
57-
getUrlWithSearchParams(ROUTES.PLUGIN_GLOBAL_LIST_V2, payload),
58-
)) as ResponseType<PluginDetailDTO>
57+
const { result } = (await get(getUrlWithSearchParams(ROUTES.PLUGIN_GLOBAL_LIST_V2, payload), {
58+
signal,
59+
})) as ResponseType<PluginDetailDTO>
5960

6061
const pluginStore = parsePluginDetailsDTOIntoPluginStore(result?.parentPlugins)
6162
return {
6263
totalCount: result.totalCount,
6364
pluginStore,
6465
}
6566
} catch (error) {
66-
showError(error)
67+
if (!getIsRequestAborted(error)) {
68+
showError(error)
69+
}
6770
throw error
6871
}
6972
}

src/Shared/Components/Plugin/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { MutableRefObject } from 'react'
12
import { VariableType } from '../../../Common'
23
import { BaseFilterQueryParams } from '../../types'
34
import { ImageWithFallbackProps } from '../ImageWithFallback'
@@ -143,6 +144,7 @@ export type PluginListContainerProps = BasePluginListContainerProps &
143144
)
144145

145146
export interface GetPluginStoreDataServiceParamsType extends Pick<PluginListFiltersType, 'searchKey' | 'selectedTags'> {
147+
signal: AbortSignal
146148
appId: number
147149
offset?: number
148150
}
@@ -188,6 +190,7 @@ export interface PluginListProps
188190
pluginList: PluginListContainerProps['parentPluginList']
189191
totalCount: PluginListContainerProps['parentTotalCount']
190192
filters: PluginListContainerProps['parentFilters']
193+
getPluginStoreRef: MutableRefObject<AbortController>
191194
}
192195

193196
export interface PluginCardProps

0 commit comments

Comments
 (0)