Skip to content

Commit d401bdc

Browse files
authored
Merge pull request #380 from oasisprotocol/lw/nexus-infinite
Refactor into useNexusInfiniteQuery
2 parents 6f62ad9 + 07ce49e commit d401bdc

4 files changed

Lines changed: 80 additions & 51 deletions

File tree

.changelog/380.trivial.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Refactor into useNexusInfiniteQuery

src/components/AppsList/index.tsx

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { useEffect, type FC, type ReactNode } from 'react'
22
import { Skeleton } from '@oasisprotocol/ui-library/src/components/ui/skeleton'
33
import { AppCard } from '../AppCard'
4-
import { getGetRuntimeRoflAppsQueryKey, GetRuntimeRoflApps } from '../../nexus/api'
4+
import { GetRuntimeRoflApps } from '../../nexus/api'
55
import { useNetwork } from '../../hooks/useNetwork'
6-
import { useInfiniteQuery } from '@tanstack/react-query'
76
import { useInView } from 'react-intersection-observer'
87
import { useAccount } from 'wagmi'
8+
import { useNexusInfiniteQuery } from '../../utils/useNexusInfiniteQuery'
99

1010
type AppsListProps = {
1111
emptyState: ReactNode
@@ -19,30 +19,22 @@ export const AppsList: FC<AppsListProps> = ({ emptyState, type }) => {
1919
// Fallback is needed to render Explore page content without wallet connection
2020
const network = useNetwork(type === 'dashboard' ? undefined : 'mainnet')
2121

22-
const appsQueryParams = (pageParam = 0) =>
23-
[
24-
network,
25-
'sapphire',
26-
{
27-
limit: pageLimit,
28-
offset: pageParam,
29-
admin: type === 'dashboard' ? address : undefined,
30-
sort_by: type === 'dashboard' ? 'created_at_desc' : undefined,
31-
},
32-
] satisfies Parameters<typeof GetRuntimeRoflApps>
33-
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isFetched } = useInfiniteQuery({
34-
queryKey: ['infinite', ...getGetRuntimeRoflAppsQueryKey(...appsQueryParams())],
35-
queryFn: async ({ pageParam = 0 }) => {
36-
const result = await GetRuntimeRoflApps(...appsQueryParams(pageParam))
37-
return result
38-
},
39-
initialPageParam: 0,
40-
enabled: type === 'explore' || (type === 'dashboard' && isConnected),
41-
getNextPageParam: (lastPage, allPages) => {
42-
const totalFetched = allPages.length * pageLimit
43-
return lastPage.data.rofl_apps.length < lastPage.data.total_count ? totalFetched : undefined
44-
},
45-
})
22+
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isFetched } =
23+
useNexusInfiniteQuery({
24+
queryKeyPrefix: 'rofl_apps',
25+
queryFn: GetRuntimeRoflApps,
26+
resultsField: 'rofl_apps',
27+
params: [
28+
network,
29+
'sapphire',
30+
{
31+
limit: pageLimit,
32+
admin: type === 'dashboard' ? address : undefined,
33+
sort_by: type === 'dashboard' ? 'created_at_desc' : undefined,
34+
},
35+
],
36+
enabled: type === 'explore' || (type === 'dashboard' && isConnected),
37+
})
4638

4739
useEffect(() => {
4840
if (inView && hasNextPage && !isFetchingNextPage) {

src/pages/Dashboard/Machines/index.tsx

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { useEffect, type FC } from 'react'
22
import { MachinesEmptyState } from './emptyState'
33
import { Skeleton } from '@oasisprotocol/ui-library/src/components/ui/skeleton'
4-
import { useInfiniteQuery } from '@tanstack/react-query'
54
import { useInView } from 'react-intersection-observer'
65
import { useAccount } from 'wagmi'
76
import { useNetwork } from '../../../hooks/useNetwork'
8-
import { getGetRuntimeRoflmarketInstancesQueryKey, GetRuntimeRoflmarketInstances } from '../../../nexus/api'
7+
import { GetRuntimeRoflmarketInstances } from '../../../nexus/api'
98
import { MachineCard } from '../../../components/MachineCard'
9+
import { useNexusInfiniteQuery } from '../../../utils/useNexusInfiniteQuery'
1010

1111
const pageLimit = 9
1212

@@ -15,29 +15,21 @@ export const Machines: FC = () => {
1515
const { ref, inView } = useInView()
1616
const network = useNetwork()
1717

18-
const machinesQueryParams = (pageParam = 0) =>
19-
[
20-
network,
21-
'sapphire',
22-
{
23-
limit: pageLimit,
24-
offset: pageParam,
25-
admin: address,
26-
},
27-
] satisfies Parameters<typeof GetRuntimeRoflmarketInstances>
28-
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isFetched } = useInfiniteQuery({
29-
queryKey: ['infinite', ...getGetRuntimeRoflmarketInstancesQueryKey(...machinesQueryParams())],
30-
queryFn: async ({ pageParam = 0 }) => {
31-
const result = await GetRuntimeRoflmarketInstances(...machinesQueryParams(pageParam))
32-
return result
33-
},
34-
initialPageParam: 0,
35-
enabled: isConnected,
36-
getNextPageParam: (lastPage, allPages) => {
37-
const totalFetched = allPages.length * pageLimit
38-
return lastPage.data.instances.length < lastPage.data.total_count ? totalFetched : undefined
39-
},
40-
})
18+
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, isFetched } =
19+
useNexusInfiniteQuery({
20+
queryKeyPrefix: 'machines',
21+
queryFn: GetRuntimeRoflmarketInstances,
22+
resultsField: 'instances',
23+
params: [
24+
network,
25+
'sapphire',
26+
{
27+
limit: pageLimit,
28+
admin: address,
29+
},
30+
],
31+
enabled: isConnected,
32+
})
4133

4234
useEffect(() => {
4335
if (inView && hasNextPage && !isFetchingNextPage) {

src/utils/useNexusInfiniteQuery.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { useInfiniteQuery } from '@tanstack/react-query'
2+
import { AxiosResponse } from 'axios'
3+
import { List } from '../nexus/api'
4+
5+
/** Strictly typed, correctly puts params in queryKey, and paginates using total_count */
6+
export function useNexusInfiniteQuery<
7+
T extends unknown[],
8+
ResultsField extends string,
9+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10+
Params extends any[],
11+
>({
12+
queryKeyPrefix,
13+
queryFn,
14+
resultsField,
15+
params,
16+
enabled,
17+
}: {
18+
queryKeyPrefix: string
19+
queryFn: (...params: Params) => Promise<AxiosResponse<List & { [k in ResultsField]: T }, unknown, unknown>>
20+
resultsField: ResultsField
21+
params: Params
22+
enabled?: boolean
23+
}) {
24+
if (!params.find(p => (p as { limit?: number } | undefined)?.limit))
25+
throw new Error('Expected some param to specify page "limit"')
26+
if (params.find(p => (p as { offset?: number } | undefined)?.offset))
27+
throw new Error('Unexpected param "offset" - it will be added automatically')
28+
29+
return useInfiniteQuery({
30+
queryKey: ['infinite', queryKeyPrefix, params],
31+
queryFn: ({ pageParam = 0 }) => {
32+
const paramsWithOffset = params.map(p =>
33+
(p as { limit?: number } | undefined)?.limit ? { ...p, offset: pageParam } : p,
34+
) as Params
35+
return queryFn(...paramsWithOffset)
36+
},
37+
initialPageParam: 0,
38+
getNextPageParam: (lastPage, allPages) => {
39+
const totalFetched = allPages.reduce((sum, p) => sum + p.data[resultsField].length, 0)
40+
return lastPage.data[resultsField].length < lastPage.data.total_count ? totalFetched : undefined
41+
},
42+
enabled: enabled,
43+
})
44+
}

0 commit comments

Comments
 (0)