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

rewrite top tokens hook
This commit is contained in:
Jordan Frankfurt 2022-09-22 13:06:31 -05:00 committed by GitHub
parent d9113fb6d4
commit 397b9d423e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 66 deletions

@ -116,28 +116,15 @@ export default function TokenTable() {
<GridContainer>
<HeaderRow />
<TokenDataContainer>
{tokens.map((token, index) => {
if (tokens.length === index + 1) {
return (
{tokens.map((token, index) => (
<LoadedRow
key={token?.name}
tokenListIndex={index}
tokenListLength={tokens?.length ?? 0}
token={token}
ref={lastTokenRef}
ref={tokens.length === index + 1 ? lastTokenRef : undefined}
/>
)
} else {
return (
<LoadedRow
key={token?.name}
tokenListIndex={index}
tokenListLength={tokens?.length ?? 0}
token={token}
/>
)
}
})}
))}
{loading && LoadingMoreRows}
</TokenDataContainer>
</GridContainer>

@ -113,7 +113,6 @@ const tokenQuery = graphql`
`
export function useTokenQuery(address: string, chain: Chain, timePeriod: TimePeriod) {
//const cachedTopToken = cachedTopTokens[address]
const data = useLazyLoadQuery<TokenQuery>(tokenQuery, {
contract: { address, chain },
duration: toHistoryDuration(timePeriod),

@ -18,9 +18,8 @@ import { toHistoryDuration, useCurrentChainName } from './util'
export function usePrefetchTopTokens() {
const duration = toHistoryDuration(useAtomValue(filterTimeAtom))
const chain = useCurrentChainName()
const top100 = useLazyLoadQuery<TopTokens100Query>(topTokens100Query, { duration, chain })
return top100
const args = useMemo(() => ({ chain, duration }), [chain, duration])
return useLazyLoadQuery<TopTokens100Query>(topTokens100Query, args)
}
const topTokens100Query = graphql`
@ -131,59 +130,62 @@ function toContractInput(token: PrefetchedTopToken) {
}
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 environment = useRelayEnvironment()
const [tokens, setTokens] = useState<TopToken[]>()
const [tokens, setTokens] = useState<TopToken[]>([])
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<TopTokens_TokensQuery>(
const prefetchedSelectedTokens = useFilteredTokens(useSortedTokens(prefetchedData.topTokens))
const contracts: ContractInput[] = useMemo(
() => prefetchedSelectedTokens.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE).map(toContractInput),
[page, prefetchedSelectedTokens]
)
useEffect(() => {
const subscription = fetchQuery<TopTokens_TokensQuery>(
environment,
tokensQuery,
{ contracts, duration },
{ fetchPolicy: 'store-or-network' }
)
.toPromise()
.then(onSuccess)
).subscribe({
start() {
setLoading(true)
},
[duration, environment]
)
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])
complete() {
setLoading(false)
setPage(page + 1)
}
},
next(data) {
appendTokens(data.tokens as TopToken[])
},
})
}, [loadTokens, page, prefetchedSelectedTokens, tokens])
return subscription.unsubscribe
}, [appendTokens, contracts, duration, environment])
// 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)
setLoading(false)
setPage(1)
}
})
}, [loadTokens, prefetchedSelectedTokens])
return { loading, tokens, loadMoreTokens }
return { loading, tokens: useFilteredTokens(useSortedTokens(tokens)) as TopToken[], loadMoreTokens }
}
export const tokensQuery = graphql`