diff --git a/src/components/Tokens/TokenTable/TokenTable.tsx b/src/components/Tokens/TokenTable/TokenTable.tsx
index 58519c733c..1ae0dd052b 100644
--- a/src/components/Tokens/TokenTable/TokenTable.tsx
+++ b/src/components/Tokens/TokenTable/TokenTable.tsx
@@ -116,28 +116,15 @@ export default function TokenTable() {
- {tokens.map((token, index) => {
- if (tokens.length === index + 1) {
- return (
-
- )
- } else {
- return (
-
- )
- }
- })}
+ {tokens.map((token, index) => (
+
+ ))}
{loading && LoadingMoreRows}
diff --git a/src/graphql/data/Token.ts b/src/graphql/data/Token.ts
index f6ac3ec033..d4448895f5 100644
--- a/src/graphql/data/Token.ts
+++ b/src/graphql/data/Token.ts
@@ -113,7 +113,6 @@ const tokenQuery = graphql`
`
export function useTokenQuery(address: string, chain: Chain, timePeriod: TimePeriod) {
- //const cachedTopToken = cachedTopTokens[address]
const data = useLazyLoadQuery(tokenQuery, {
contract: { address, chain },
duration: toHistoryDuration(timePeriod),
diff --git a/src/graphql/data/TopTokens.ts b/src/graphql/data/TopTokens.ts
index dbf4ee1536..bdda7989ce 100644
--- a/src/graphql/data/TopTokens.ts
+++ b/src/graphql/data/TopTokens.ts
@@ -18,9 +18,8 @@ import { toHistoryDuration, useCurrentChainName } from './util'
export function usePrefetchTopTokens() {
const duration = toHistoryDuration(useAtomValue(filterTimeAtom))
const chain = useCurrentChainName()
-
- const top100 = useLazyLoadQuery(topTokens100Query, { duration, chain })
- return top100
+ const args = useMemo(() => ({ chain, duration }), [chain, duration])
+ return useLazyLoadQuery(topTokens100Query, args)
}
const topTokens100Query = graphql`
@@ -131,59 +130,62 @@ function toContractInput(token: PrefetchedTopToken) {
}
export type TopToken = NonNullable[number]
-export function useTopTokens(prefetchedData: TopTokens100Query['response']) {
+interface UseTopTokensReturnValue {
+ loading: boolean
+ tokens: TopToken[]
+ loadMoreTokens: () => void
+}
+export function useTopTokens(prefetchedData: TopTokens100Query['response']): UseTopTokensReturnValue {
const duration = toHistoryDuration(useAtomValue(filterTimeAtom))
const environment = useRelayEnvironment()
- const [tokens, setTokens] = useState()
+ const [tokens, setTokens] = useState([])
- const [page, setPage] = useState(1)
- const prefetchedSelectedTokens = useFilteredTokens(useSortedTokens(prefetchedData.topTokens))
+ const [page, setPage] = useState(0)
const [loading, setLoading] = useState(true)
+ const appendTokens = useCallback(
+ (newTokens: TopToken[]) => {
+ setTokens(
+ Object.values(
+ tokens
+ .concat(newTokens)
+ .reduce((acc, token) => (token?.address ? { ...acc, [token.address]: token } : acc), {})
+ )
+ )
+ },
+ [tokens]
+ )
+ const loadMoreTokens = useCallback(() => setPage(page + 1), [page])
+
// TopTokens should ideally be fetched with usePaginationFragment. The backend does not current support graphql cursors;
// in the meantime, fetchQuery is used, as other relay hooks do not allow the refreshing and lazy loading we need
- const loadTokens = useCallback(
- (contracts: ContractInput[], onSuccess: (data: TopTokens_TokensQuery['response'] | undefined) => void) => {
- fetchQuery(
- environment,
- tokensQuery,
- { contracts, duration },
- { fetchPolicy: 'store-or-network' }
- )
- .toPromise()
- .then(onSuccess)
- },
- [duration, environment]
+ const prefetchedSelectedTokens = useFilteredTokens(useSortedTokens(prefetchedData.topTokens))
+ const contracts: ContractInput[] = useMemo(
+ () => prefetchedSelectedTokens.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE).map(toContractInput),
+ [page, prefetchedSelectedTokens]
)
- const loadMoreTokens = useCallback(() => {
- setLoading(true)
- const contracts = prefetchedSelectedTokens.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE).map(toContractInput)
- loadTokens(contracts, (data) => {
- if (data?.tokens) {
- setTokens([...(tokens ?? []), ...data.tokens])
- setLoading(false)
- setPage(page + 1)
- }
- })
- }, [loadTokens, page, prefetchedSelectedTokens, tokens])
-
- // Reset count when filters are changed
useEffect(() => {
- setLoading(true)
- setTokens([])
- const contracts = prefetchedSelectedTokens.slice(0, PAGE_SIZE).map(toContractInput)
- loadTokens(contracts, (data) => {
- if (data?.tokens) {
- // @ts-ignore prevent typescript from complaining about readonly data
- setTokens(data.tokens)
+ const subscription = fetchQuery(
+ environment,
+ tokensQuery,
+ { contracts, duration },
+ { fetchPolicy: 'store-or-network' }
+ ).subscribe({
+ start() {
+ setLoading(true)
+ },
+ complete() {
setLoading(false)
- setPage(1)
- }
+ },
+ next(data) {
+ appendTokens(data.tokens as TopToken[])
+ },
})
- }, [loadTokens, prefetchedSelectedTokens])
+ return subscription.unsubscribe
+ }, [appendTokens, contracts, duration, environment])
- return { loading, tokens, loadMoreTokens }
+ return { loading, tokens: useFilteredTokens(useSortedTokens(tokens)) as TopToken[], loadMoreTokens }
}
export const tokensQuery = graphql`