Skip to content

Commit

Permalink
refactor: infinite scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Aug 24, 2023
1 parent 9acf197 commit a608c5c
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 71 deletions.
2 changes: 1 addition & 1 deletion src/entries/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { syncStores } from '~/zustand'
import { getMessenger } from '../../messengers'
import { handleCommands } from './commands'
import { setupContextMenu } from './context-menu'
import { setupExtensionId } from './extension-id'
import { setupInpage } from './inpage'
import { setupRpcHandler } from './rpc'
import { syncStores } from '~/zustand'

getMessenger('background:contentScript').reply('ping', async () => 'pong')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,36 @@ import { createQueryKey, queryClient } from '~/react-query'
import { useBlock } from './useBlock'
import { useClient } from './useClient'

export const getBlockTransactionsQueryKey = createQueryKey<
export const getInfiniteBlockTransactionsQueryKey = createQueryKey<
'block-transactions',
[key: Client['key']]
>('block-transactions')

export function useBlockTransactionsQueryOptions() {
export function useInfiniteBlockTransactionsQueryOptions() {
const { data: block } = useBlock({ gcTime: 0 })
const client = useClient()
const limit = 10
const limit_ = 10

return {
enabled: Boolean(block?.number),
defaultPageParam: 0,
getNextPageParam: (_: unknown, pages: unknown[]) => pages.length,
queryKey: getBlockTransactionsQueryKey([client.key]),
queryKey: getInfiniteBlockTransactionsQueryKey([client.key]),
async queryFn({ pageParam }: { pageParam: number }) {
let blockNumber = block?.number!
if (pageParam > 0) {
const prevInfiniteTransactions = queryClient.getQueryData([
'transactions',
client.key,
]) as InfiniteData<Transaction[]>
const transactions = prevInfiniteTransactions.pages[pageParam - 1]
blockNumber = transactions[transactions.length - 1].blockNumber! - 1n
let limit = limit_

const prevInfiniteTransactions = queryClient.getQueryData([
'block-transactions',
client.key,
]) as InfiniteData<Transaction[]>
if (prevInfiniteTransactions) {
if (pageParam > 0) {
const transactions = prevInfiniteTransactions.pages[pageParam - 1]
blockNumber = transactions[transactions.length - 1].blockNumber! - 1n
} else {
limit = prevInfiniteTransactions.pages[0].length || limit
}
}

let transactions: Transaction[] = []
Expand All @@ -46,7 +52,7 @@ export function useBlockTransactionsQueryOptions() {
}
}

export function useBlockTransactions() {
const queryOptions = useBlockTransactionsQueryOptions()
export function useInfiniteBlockTransactions() {
const queryOptions = useInfiniteBlockTransactionsQueryOptions()
return useInfiniteQuery(queryOptions)
}
35 changes: 22 additions & 13 deletions src/hooks/useBlocks.ts → src/hooks/useInfiniteBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,36 @@ import { createQueryKey, queryClient } from '~/react-query'
import { useBlock } from './useBlock'
import { useClient } from './useClient'

export const getBlocksQueryKey = createQueryKey<'blocks', [key: Client['key']]>(
export const getInfiniteBlocksQueryKey = createQueryKey<
'blocks',
)
[key: Client['key']]
>('blocks')

export function useInfiniteBlocksQueryOptions() {
const limit_ = 10

export function useBlocksQueryOptions({ limit = 10 }: { limit?: number } = {}) {
const { data: block } = useBlock({ gcTime: 0 })
const client = useClient()
return {
enabled: Boolean(block?.number),
defaultPageParam: 0,
getNextPageParam: (_: unknown, pages: unknown[]) => pages.length,
queryKey: getBlocksQueryKey([client.key]),
queryKey: getInfiniteBlocksQueryKey([client.key]),
async queryFn({ pageParam }: { pageParam: number }) {
let blockNumber = block?.number!
if (pageParam > 0) {
const prevInfiniteBlocks = queryClient.getQueryData([
'blocks',
client.key,
]) as InfiniteData<Block[]>
const block = prevInfiniteBlocks.pages[pageParam - 1]
blockNumber = block[block.length - 1].number! - 1n
let limit = limit_

const prevInfiniteBlocks = queryClient.getQueryData([
'blocks',
client.key,
]) as InfiniteData<Block[]>
if (prevInfiniteBlocks) {
if (pageParam > 0) {
const block = prevInfiniteBlocks.pages[pageParam - 1]
blockNumber = block[block.length - 1].number! - 1n
} else {
limit = prevInfiniteBlocks.pages[0].length || limit
}
}

return (
Expand All @@ -39,7 +48,7 @@ export function useBlocksQueryOptions({ limit = 10 }: { limit?: number } = {}) {
}
}

export function useBlocks({ limit = 10 }: { limit?: number } = {}) {
const queryOptions = useBlocksQueryOptions({ limit })
export function useInfiniteBlocks() {
const queryOptions = useInfiniteBlocksQueryOptions()
return useInfiniteQuery(queryOptions)
}
30 changes: 11 additions & 19 deletions src/hooks/usePendingBlock.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { type InfiniteData, useQuery } from '@tanstack/react-query'
import type { Block, Client, Transaction } from 'viem'

import { createQueryKey, queryClient } from '~/react-query'
import {
createQueryKey,
queryClient,
updateInfiniteQueryData,
} from '~/react-query'
import { useNetworkStore } from '~/zustand'

import { getBalanceQueryKey } from './useBalance'
import { getBlockQueryKey } from './useBlock'
import { getBlockTransactionsQueryKey } from './useBlockTransactions'
import { getBlocksQueryKey } from './useBlocks'
import { useClient } from './useClient'
import { getInfiniteBlockTransactionsQueryKey } from './useInfiniteBlockTransactions'
import { getInfiniteBlocksQueryKey } from './useInfiniteBlocks'
import { useNetworkStatus } from './useNetworkStatus'
import { getNonceQueryKey } from './useNonce'
import { getPendingTransactionsQueryKey } from './usePendingTransactions'
Expand Down Expand Up @@ -68,24 +72,12 @@ export function usePendingBlockQueryOptions({
includeTransactions: true,
})
queryClient.setQueryData<InfiniteData<Block[]>>(
getBlocksQueryKey([client.key]),
(data) => {
if (!data) return
return {
...data,
pages: [[latestBlock], ...data.pages],
}
},
getInfiniteBlocksQueryKey([client.key]),
updateInfiniteQueryData<Block[]>([latestBlock]),
)
queryClient.setQueryData<InfiniteData<Transaction[]>>(
getBlockTransactionsQueryKey([client.key]),
(data) => {
if (!data) return
return {
...data,
pages: [[...latestBlock.transactions], ...data.pages],
}
},
getInfiniteBlockTransactionsQueryKey([client.key]),
updateInfiniteQueryData<Transaction[]>([...latestBlock.transactions]),
)

return block || null
Expand Down
4 changes: 2 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { numberToHex } from 'viem'

import { getTheme, setTheme } from '~/design-system'
import '~/design-system/styles/global.css'
import { getBlocksQueryKey } from '~/hooks/useBlocks'
import { useClient } from '~/hooks/useClient'
import { getInfiniteBlocksQueryKey } from '~/hooks/useInfiniteBlocks'
import { useNetworkStatus } from '~/hooks/useNetworkStatus'
import { usePendingBlock } from '~/hooks/usePendingBlock'
import { usePrevious } from '~/hooks/usePrevious'
Expand Down Expand Up @@ -199,7 +199,7 @@ function SyncNetwork() {
useEffect(() => {
// Reset blocks query when node comes back online.
if (!prevListening && listening) {
queryClient.resetQueries({ queryKey: getBlocksQueryKey() })
queryClient.resetQueries({ queryKey: getInfiniteBlocksQueryKey() })
}
}, [prevListening, listening])

Expand Down
52 changes: 36 additions & 16 deletions src/react-query.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
import { QueryClient } from '@tanstack/react-query'
import { type InfiniteData, QueryClient } from '@tanstack/react-query'
import {
PersistQueryClientProvider,
type PersistedClient,
Expand All @@ -8,21 +8,6 @@ import type { ReactNode } from 'react'

import { webextStorage } from './storage'

type RecursiveDeps<deps extends readonly unknown[]> = deps extends [
infer dep,
...infer rest,
]
? [dep] | [dep, ...RecursiveDeps<rest>]
: []

export function createQueryKey<
key extends string,
deps extends readonly unknown[],
>(id: key) {
return (deps?: RecursiveDeps<deps>) =>
[id, ...(deps ? deps : [])] as unknown as [key, ...deps]
}

export const queryClient = new QueryClient({
defaultOptions: {
queries: {
Expand Down Expand Up @@ -64,3 +49,38 @@ export function QueryClientProvider({ children }: { children: ReactNode }) {
</PersistQueryClientProvider>
)
}

////////////////////////////////////////////////////////////////////////
// Utils

type RecursiveDeps<deps extends readonly unknown[]> = deps extends [
infer dep,
...infer rest,
]
? [dep] | [dep, ...RecursiveDeps<rest>]
: []

export function createQueryKey<
key extends string,
deps extends readonly unknown[],
>(id: key) {
return (deps?: RecursiveDeps<deps>) =>
[id, ...(deps ? deps : [])] as unknown as [key, ...deps]
}

export function updateInfiniteQueryData<data extends unknown[]>(data: data) {
return (prev: InfiniteData<data> | undefined) => {
if (!prev) return
const [first, ...rest] = prev.pages
if (first.length > rest?.[rest.length - 1]?.length)
return {
...prev,
pageParams: [...prev.pageParams, prev.pageParams.length],
pages: [data, first, ...rest],
}
return {
...prev,
pages: [[...data, ...first], ...rest],
}
}
}
22 changes: 15 additions & 7 deletions src/screens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import {
} from '~/design-system'
import { useAccounts } from '~/hooks/useAccounts'
import { useBalance } from '~/hooks/useBalance'
import { useBlockTransactions } from '~/hooks/useBlockTransactions'
import { useBlocks } from '~/hooks/useBlocks'
import { useClient } from '~/hooks/useClient'
import { useInfiniteBlockTransactions } from '~/hooks/useInfiniteBlockTransactions'
import { useInfiniteBlocks } from '~/hooks/useInfiniteBlocks'
import { useNonce } from '~/hooks/useNonce'
import { usePendingBlock } from '~/hooks/usePendingBlock'
import { usePendingTransactions } from '~/hooks/usePendingTransactions'
Expand Down Expand Up @@ -331,8 +331,9 @@ function Blocks() {
const {
data: infiniteBlocks,
fetchNextPage,
isFetching,
isFetchingNextPage,
} = useBlocks()
} = useInfiniteBlocks()
const blocks = [
{ block: pendingBlock, status: 'pending' },
...(infiniteBlocks?.pages
Expand All @@ -354,9 +355,10 @@ function Blocks() {

const { ref, inView } = useInView()
useEffect(() => {
if (isFetching) return
if (isFetchingNextPage) return
if (inView) fetchNextPage()
}, [fetchNextPage, inView, isFetchingNextPage])
}, [fetchNextPage, inView, isFetching, isFetchingNextPage])

return (
<Box
Expand Down Expand Up @@ -447,8 +449,9 @@ function Transactions() {
const {
data: infiniteTransactions,
fetchNextPage,
isFetching,
isFetchingNextPage,
} = useBlockTransactions()
} = useInfiniteBlockTransactions()
const transactions = [
...(pendingTransactions?.map((transaction) => ({
transaction,
Expand All @@ -468,9 +471,13 @@ function Transactions() {

const { ref, inView } = useInView()
useEffect(() => {
if (isFetching) return
if (isFetchingNextPage) return
if (inView) fetchNextPage()
}, [fetchNextPage, inView, isFetchingNextPage])
if (inView) {
console.log('test')
fetchNextPage()
}
}, [fetchNextPage, inView, isFetching, isFetchingNextPage])

return (
<Box
Expand Down Expand Up @@ -547,6 +554,7 @@ function Transactions() {
})}
</Box>
<Inset space="12px">
<Box onClick={() => fetchNextPage()}>more</Box>
<Box ref={ref}>
<Text color="text/tertiary">Loading...</Text>
</Box>
Expand Down

0 comments on commit a608c5c

Please sign in to comment.