refactor: lazy load asset details and profile page (#5203)

* properly load NFtBalance data

* lazy load asset details

* extend useLoadNftBalance

* handle different balance query formats

* correct load params
This commit is contained in:
Charles Bachmeier 2022-11-14 17:38:02 -05:00 committed by GitHub
parent 77a6d158ea
commit 7b086848bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 26 deletions

@ -1,7 +1,8 @@
import { parseEther } from '@ethersproject/units'
import graphql from 'babel-plugin-relay/macro'
import { CollectionInfoForAsset, GenieAsset, SellOrder, TokenType } from 'nft/types'
import { useLazyLoadQuery } from 'react-relay'
import { useEffect } from 'react'
import { useLazyLoadQuery, useQueryLoader } from 'react-relay'
import { DetailsQuery } from './__generated__/DetailsQuery.graphql'
@ -91,11 +92,24 @@ const detailsQuery = graphql`
}
`
export function useLoadDetailsQuery(address?: string, tokenId?: string): void {
const [, loadQuery] = useQueryLoader(detailsQuery)
useEffect(() => {
if (address && tokenId) {
loadQuery({ address, tokenId })
}
}, [address, tokenId, loadQuery])
}
export function useDetailsQuery(address: string, tokenId: string): [GenieAsset, CollectionInfoForAsset] | undefined {
const queryData = useLazyLoadQuery<DetailsQuery>(detailsQuery, {
address,
tokenId,
})
const queryData = useLazyLoadQuery<DetailsQuery>(
detailsQuery,
{
address,
tokenId,
},
{ fetchPolicy: 'store-or-network' }
)
const asset = queryData.nftAssets?.edges[0]?.node
const collection = asset?.collection

@ -1,7 +1,9 @@
import graphql from 'babel-plugin-relay/macro'
import { parseEther } from 'ethers/lib/utils'
import { DEFAULT_WALLET_ASSET_QUERY_AMOUNT } from 'nft/components/profile/view/ProfilePage'
import { WalletAsset } from 'nft/types'
import { useLazyLoadQuery, usePaginationFragment } from 'react-relay'
import { useEffect } from 'react'
import { useLazyLoadQuery, usePaginationFragment, useQueryLoader } from 'react-relay'
import { NftBalancePaginationQuery } from './__generated__/NftBalancePaginationQuery.graphql'
import { NftBalanceQuery } from './__generated__/NftBalanceQuery.graphql'
@ -111,26 +113,54 @@ const nftBalanceQuery = graphql`
type NftBalanceQueryAsset = NonNullable<
NonNullable<NonNullable<NftBalanceQuery_nftBalances$data['nftBalances']>['edges']>[number]
>
//
// export type TokenQueryData = NonNullable<TokenQuery$data['tokens']>[number]
export function useLoadNftBalanceQuery(
ownerAddress?: string,
collectionAddress?: string | string[],
tokenId?: string
): void {
const [, loadQuery] = useQueryLoader(nftBalanceQuery)
useEffect(() => {
if (ownerAddress) {
loadQuery({
ownerAddress,
filter: tokenId
? { assets: [{ address: collectionAddress, tokenId }] }
: { addresses: Array.isArray(collectionAddress) ? collectionAddress : [collectionAddress] },
first: tokenId ? 1 : DEFAULT_WALLET_ASSET_QUERY_AMOUNT,
})
}
}, [ownerAddress, loadQuery, collectionAddress, tokenId])
}
export function useNftBalanceQuery(
ownerAddress: string,
collectionFilters?: string[],
assetsFilter?: { address: string; tokenId: string }[],
first?: number,
after?: string,
last?: number,
before?: string
) {
const queryData = useLazyLoadQuery<NftBalanceQuery>(nftBalanceQuery, {
ownerAddress,
filter: {
addresses: collectionFilters,
const queryData = useLazyLoadQuery<NftBalanceQuery>(
nftBalanceQuery,
{
ownerAddress,
filter:
assetsFilter && assetsFilter.length > 0
? {
assets: assetsFilter,
}
: {
addresses: collectionFilters,
},
first,
after,
last,
before,
},
first,
after,
last,
before,
})
{ fetchPolicy: 'store-or-network' }
)
const { data, hasNext, loadNext, isLoadingNext } = usePaginationFragment<NftBalancePaginationQuery, any>(
nftBalancePaginationQuery,
queryData

@ -20,9 +20,14 @@ import {
} from 'nft/hooks'
import { ScreenBreakpointsPaddings } from 'nft/pages/collection/index.css'
import { OSCollectionsFetcher } from 'nft/queries'
import { TokenType } from 'nft/types'
import { UniformHeight, UniformHeights } from 'nft/types'
import { ProfilePageStateType, WalletAsset, WalletCollection } from 'nft/types'
import {
ProfilePageStateType,
TokenType,
UniformHeight,
UniformHeights,
WalletAsset,
WalletCollection,
} from 'nft/types'
import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'
import InfiniteScroll from 'react-infinite-scroll-component'
import { useQuery } from 'react-query'
@ -109,7 +114,7 @@ export const ProfilePage = () => {
walletAssets: ownerAssets,
loadNext,
hasNext,
} = useNftBalanceQuery(address, collectionFilters, DEFAULT_WALLET_ASSET_QUERY_AMOUNT)
} = useNftBalanceQuery(address, collectionFilters, [], DEFAULT_WALLET_ASSET_QUERY_AMOUNT)
useEffect(() => {
ownerCollections && setWalletCollections(ownerCollections)

@ -1,9 +1,10 @@
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useDetailsQuery } from 'graphql/data/nft/Details'
import { useDetailsQuery, useLoadDetailsQuery } from 'graphql/data/nft/Details'
import { AssetDetails } from 'nft/components/details/AssetDetails'
import { AssetDetailsLoading } from 'nft/components/details/AssetDetailsLoading'
import { AssetPriceDetails } from 'nft/components/details/AssetPriceDetails'
import { useMemo } from 'react'
import { Suspense, useMemo } from 'react'
import { useParams } from 'react-router-dom'
import styled from 'styled-components/macro'
@ -60,4 +61,15 @@ const Asset = () => {
)
}
export default Asset
const AssetPage = () => {
const { tokenId, contractAddress } = useParams()
useLoadDetailsQuery(contractAddress, tokenId)
return (
<Suspense fallback={<AssetDetailsLoading />}>
<Asset />
</Suspense>
)
}
export default AssetPage

@ -1,16 +1,18 @@
import { Trace } from '@uniswap/analytics'
import { PageName } from '@uniswap/analytics-events'
import { useWeb3React } from '@web3-react/core'
import { useLoadNftBalanceQuery } from 'graphql/data/nft/NftBalance'
import { Box } from 'nft/components/Box'
import { Center, Column, Row } from 'nft/components/Flex'
import { ChevronLeftIcon, XMarkIcon } from 'nft/components/icons'
import { ListPage } from 'nft/components/profile/list/ListPage'
import { ProfilePage } from 'nft/components/profile/view/ProfilePage'
import { ProfilePageLoadingSkeleton } from 'nft/components/profile/view/ProfilePageLoadingSkeleton'
import { buttonMedium, headlineMedium, headlineSmall } from 'nft/css/common.css'
import { themeVars } from 'nft/css/sprinkles.css'
import { useBag, useNFTList, useProfilePageState, useSellAsset, useWalletCollections } from 'nft/hooks'
import { ListingStatus, ProfilePageStateType } from 'nft/types'
import { useEffect } from 'react'
import { Suspense, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useToggleWalletModal } from 'state/application/hooks'
@ -18,7 +20,7 @@ import * as styles from './sell.css'
const SHOPPING_BAG_WIDTH = 360
const Profile = () => {
const ProfileContent = () => {
const sellPageState = useProfilePageState((state) => state.state)
const setSellPageState = useProfilePageState((state) => state.setProfilePageState)
const removeAllMarketplaceWarnings = useSellAsset((state) => state.removeAllMarketplaceWarnings)
@ -88,4 +90,15 @@ const Profile = () => {
)
}
const Profile = () => {
const { account } = useWeb3React()
useLoadNftBalanceQuery(account, [])
return (
<Suspense fallback={<ProfilePageLoadingSkeleton />}>
<ProfileContent />
</Suspense>
)
}
export default Profile