Commit 397b9d42 authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

feat(explore): rewrite top tokens hook (#4697)

rewrite top tokens hook
parent d9113fb6
...@@ -116,28 +116,15 @@ export default function TokenTable() { ...@@ -116,28 +116,15 @@ export default function TokenTable() {
<GridContainer> <GridContainer>
<HeaderRow /> <HeaderRow />
<TokenDataContainer> <TokenDataContainer>
{tokens.map((token, index) => { {tokens.map((token, index) => (
if (tokens.length === index + 1) {
return (
<LoadedRow
key={token?.name}
tokenListIndex={index}
tokenListLength={tokens?.length ?? 0}
token={token}
ref={lastTokenRef}
/>
)
} else {
return (
<LoadedRow <LoadedRow
key={token?.name} key={token?.name}
tokenListIndex={index} tokenListIndex={index}
tokenListLength={tokens?.length ?? 0} tokenListLength={tokens?.length ?? 0}
token={token} token={token}
ref={tokens.length === index + 1 ? lastTokenRef : undefined}
/> />
) ))}
}
})}
{loading && LoadingMoreRows} {loading && LoadingMoreRows}
</TokenDataContainer> </TokenDataContainer>
</GridContainer> </GridContainer>
......
...@@ -113,7 +113,6 @@ const tokenQuery = graphql` ...@@ -113,7 +113,6 @@ const tokenQuery = graphql`
` `
export function useTokenQuery(address: string, chain: Chain, timePeriod: TimePeriod) { export function useTokenQuery(address: string, chain: Chain, timePeriod: TimePeriod) {
//const cachedTopToken = cachedTopTokens[address]
const data = useLazyLoadQuery<TokenQuery>(tokenQuery, { const data = useLazyLoadQuery<TokenQuery>(tokenQuery, {
contract: { address, chain }, contract: { address, chain },
duration: toHistoryDuration(timePeriod), duration: toHistoryDuration(timePeriod),
......
...@@ -18,9 +18,8 @@ import { toHistoryDuration, useCurrentChainName } from './util' ...@@ -18,9 +18,8 @@ import { toHistoryDuration, useCurrentChainName } from './util'
export function usePrefetchTopTokens() { export function usePrefetchTopTokens() {
const duration = toHistoryDuration(useAtomValue(filterTimeAtom)) const duration = toHistoryDuration(useAtomValue(filterTimeAtom))
const chain = useCurrentChainName() const chain = useCurrentChainName()
const args = useMemo(() => ({ chain, duration }), [chain, duration])
const top100 = useLazyLoadQuery<TopTokens100Query>(topTokens100Query, { duration, chain }) return useLazyLoadQuery<TopTokens100Query>(topTokens100Query, args)
return top100
} }
const topTokens100Query = graphql` const topTokens100Query = graphql`
...@@ -131,59 +130,62 @@ function toContractInput(token: PrefetchedTopToken) { ...@@ -131,59 +130,62 @@ function toContractInput(token: PrefetchedTopToken) {
} }
export type TopToken = NonNullable<TopTokens_TokensQuery['response']['tokens']>[number] export type TopToken = NonNullable<TopTokens_TokensQuery['response']['tokens']>[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 duration = toHistoryDuration(useAtomValue(filterTimeAtom))
const environment = useRelayEnvironment() const environment = useRelayEnvironment()
const [tokens, setTokens] = useState<TopToken[]>() const [tokens, setTokens] = useState<TopToken[]>([])
const [page, setPage] = useState(1) const [page, setPage] = useState(0)
const prefetchedSelectedTokens = useFilteredTokens(useSortedTokens(prefetchedData.topTokens))
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
// TopTokens should ideally be fetched with usePaginationFragment. The backend does not current support graphql cursors; const appendTokens = useCallback(
// in the meantime, fetchQuery is used, as other relay hooks do not allow the refreshing and lazy loading we need (newTokens: TopToken[]) => {
const loadTokens = useCallback( setTokens(
(contracts: ContractInput[], onSuccess: (data: TopTokens_TokensQuery['response'] | undefined) => void) => { Object.values(
fetchQuery<TopTokens_TokensQuery>( tokens
environment, .concat(newTokens)
tokensQuery, .reduce((acc, token) => (token?.address ? { ...acc, [token.address]: token } : acc), {})
{ contracts, duration }, )
{ fetchPolicy: 'store-or-network' }
) )
.toPromise()
.then(onSuccess)
}, },
[duration, environment] [tokens]
) )
const loadMoreTokens = useCallback(() => setPage(page + 1), [page])
const loadMoreTokens = useCallback(() => { // TopTokens should ideally be fetched with usePaginationFragment. The backend does not current support graphql cursors;
setLoading(true) // in the meantime, fetchQuery is used, as other relay hooks do not allow the refreshing and lazy loading we need
const contracts = prefetchedSelectedTokens.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE).map(toContractInput) const prefetchedSelectedTokens = useFilteredTokens(useSortedTokens(prefetchedData.topTokens))
loadTokens(contracts, (data) => { const contracts: ContractInput[] = useMemo(
if (data?.tokens) { () => prefetchedSelectedTokens.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE).map(toContractInput),
setTokens([...(tokens ?? []), ...data.tokens]) [page, prefetchedSelectedTokens]
setLoading(false) )
setPage(page + 1)
}
})
}, [loadTokens, page, prefetchedSelectedTokens, tokens])
// Reset count when filters are changed
useEffect(() => { useEffect(() => {
const subscription = fetchQuery<TopTokens_TokensQuery>(
environment,
tokensQuery,
{ contracts, duration },
{ fetchPolicy: 'store-or-network' }
).subscribe({
start() {
setLoading(true) setLoading(true)
setTokens([]) },
const contracts = prefetchedSelectedTokens.slice(0, PAGE_SIZE).map(toContractInput) complete() {
loadTokens(contracts, (data) => {
if (data?.tokens) {
// @ts-ignore prevent typescript from complaining about readonly data
setTokens(data.tokens)
setLoading(false) 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` export const tokensQuery = graphql`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment