Skip to content

Commit

Permalink
Merge pull request #1823 from blockscout/address-tabs-loading
Browse files Browse the repository at this point in the history
Address tabs loading
  • Loading branch information
isstuev authored Apr 16, 2024
2 parents ab3e070 + bbec6bc commit 57b54a6
Show file tree
Hide file tree
Showing 43 changed files with 208 additions and 61 deletions.
11 changes: 11 additions & 0 deletions lib/hooks/useIsMounted.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

export default function useIsMounted() {
const [ isMounted, setIsMounted ] = React.useState(false);

React.useEffect(() => {
setIsMounted(true);
}, [ ]);

return isMounted;
}
3 changes: 1 addition & 2 deletions pages/address/[hash]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { GetServerSideProps, NextPage } from 'next';
import dynamic from 'next/dynamic';
import React from 'react';

import type { Route } from 'nextjs-routes';
Expand All @@ -11,7 +10,7 @@ import fetchApi from 'nextjs/utils/fetchApi';

import config from 'configs/app';
import getQueryParamString from 'lib/router/getQueryParamString';
const Address = dynamic(() => import('ui/pages/Address'), { ssr: false });
import Address from 'ui/pages/Address';

const pathname: Route['pathname'] = '/address/[hash]';

Expand Down
9 changes: 8 additions & 1 deletion ui/address/AddressAccountHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { NovesHistoryFilterValue } from 'types/api/noves';
import { NovesHistoryFilterValues } from 'types/api/noves';

import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import { NOVES_TRANSLATE } from 'stubs/noves/NovesTranslate';
import { generateListStub } from 'stubs/utils';
Expand All @@ -25,10 +26,12 @@ const getFilterValue = (getFilterValueFromQuery<NovesHistoryFilterValue>).bind(n

type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
}

const AddressAccountHistory = ({ scrollRef }: Props) => {
const AddressAccountHistory = ({ scrollRef, shouldRender = true }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();

const currentAddress = getQueryParamString(router.query.hash).toLowerCase();

Expand All @@ -49,6 +52,10 @@ const AddressAccountHistory = ({ scrollRef }: Props) => {
setFilterValue(newVal);
}, [ ]);

if (!isMounted || !shouldRender) {
return null;
}

const actionBar = (
<ActionBar mt={ -6 } pb={{ base: 6, md: 5 }}>
<AccountHistoryFilter
Expand Down
9 changes: 8 additions & 1 deletion ui/address/AddressBlocksValidated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { AddressBlocksValidatedResponse } from 'types/api/address';

import config from 'configs/app';
import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMounted from 'lib/hooks/useIsMounted';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import { currencyUnits } from 'lib/units';
Expand All @@ -25,12 +26,14 @@ import AddressBlocksValidatedTableItem from './blocksValidated/AddressBlocksVali

interface Props {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
}

const AddressBlocksValidated = ({ scrollRef }: Props) => {
const AddressBlocksValidated = ({ scrollRef, shouldRender = true }: Props) => {
const [ socketAlert, setSocketAlert ] = React.useState(false);
const queryClient = useQueryClient();
const router = useRouter();
const isMounted = useIsMounted();

const addressHash = String(router.query.hash);
const query = useQueryWithPages({
Expand Down Expand Up @@ -84,6 +87,10 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
handler: handleNewSocketMessage,
});

if (!isMounted || !shouldRender) {
return null;
}

const content = query.data?.items ? (
<>
{ socketAlert && <SocketAlert mb={ 6 }/> }
Expand Down
13 changes: 12 additions & 1 deletion ui/address/AddressCoinBalance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { SocketMessage } from 'lib/socket/types';
import type { AddressCoinBalanceHistoryResponse } from 'types/api/address';

import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
Expand All @@ -17,10 +18,16 @@ import SocketAlert from 'ui/shared/SocketAlert';
import AddressCoinBalanceChart from './coinBalance/AddressCoinBalanceChart';
import AddressCoinBalanceHistory from './coinBalance/AddressCoinBalanceHistory';

const AddressCoinBalance = () => {
type Props = {
shouldRender?: boolean;
}

const AddressCoinBalance = ({ shouldRender = true }: Props) => {
const [ socketAlert, setSocketAlert ] = React.useState(false);
const queryClient = useQueryClient();
const router = useRouter();
const isMounted = useIsMounted();

const scrollRef = React.useRef<HTMLDivElement>(null);

const addressHash = getQueryParamString(router.query.hash);
Expand Down Expand Up @@ -78,6 +85,10 @@ const AddressCoinBalance = () => {
handler: handleNewSocketMessage,
});

if (!isMounted || !shouldRender) {
return null;
}

return (
<>
{ socketAlert && <SocketAlert mb={ 6 }/> }
Expand Down
5 changes: 4 additions & 1 deletion ui/address/AddressDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useRouter } from 'next/router';
import React from 'react';

import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import ServiceDegradationWarning from 'ui/shared/alerts/ServiceDegradationWarning';
Expand Down Expand Up @@ -60,6 +61,8 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
has_validated_blocks: false,
}), [ addressHash ]);

const isMounted = useIsMounted();

// error handling (except 404 codes)
if (addressQuery.isError) {
if (isCustomAppError(addressQuery.error)) {
Expand All @@ -74,7 +77,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {

const data = addressQuery.isError ? error404Data : addressQuery.data;

if (!data) {
if (!data || !isMounted) {
return null;
}

Expand Down
13 changes: 12 additions & 1 deletion ui/address/AddressInternalTxs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type { AddressFromToFilter } from 'types/api/address';
import { AddressFromToFilterValues } from 'types/api/address';

import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
import useIsMounted from 'lib/hooks/useIsMounted';
import { apos } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString';
import { INTERNAL_TX } from 'stubs/internalTx';
Expand All @@ -22,8 +23,14 @@ import AddressIntTxsList from './internals/AddressIntTxsList';

const getFilterValue = (getFilterValueFromQuery<AddressFromToFilter>).bind(null, AddressFromToFilterValues);

const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}) => {
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
}
const AddressInternalTxs = ({ scrollRef, shouldRender = true }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();

const [ filterValue, setFilterValue ] = React.useState<AddressFromToFilter>(getFilterValue(router.query.filter));

const hash = getQueryParamString(router.query.hash);
Expand Down Expand Up @@ -55,6 +62,10 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
onFilterChange({ filter: newVal });
}, [ onFilterChange ]);

if (!isMounted || !shouldRender) {
return null;
}

const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
Expand Down
13 changes: 12 additions & 1 deletion ui/address/AddressLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useRouter } from 'next/router';
import React from 'react';

import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import { LOG } from 'stubs/log';
import { generateListStub } from 'stubs/utils';
Expand All @@ -12,8 +13,14 @@ import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';

import AddressCsvExportLink from './AddressCsvExportLink';

const AddressLogs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}) => {
type Props ={
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
}

const AddressLogs = ({ scrollRef, shouldRender = true }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();

const hash = getQueryParamString(router.query.hash);
const { data, isPlaceholderData, isError, pagination } = useQueryWithPages({
Expand Down Expand Up @@ -41,6 +48,10 @@ const AddressLogs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>
</ActionBar>
);

if (!isMounted || !shouldRender) {
return null;
}

const content = data?.items ? data.items.map((item, index) => <LogItem key={ index } { ...item } type="address" isLoading={ isPlaceholderData }/>) : null;

return (
Expand Down
25 changes: 16 additions & 9 deletions ui/address/AddressTokenTransfers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getResourceKey } from 'lib/api/useApiQuery';
import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useIsMounted from 'lib/hooks/useIsMounted';
import { apos } from 'lib/html-entities';
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
Expand Down Expand Up @@ -63,14 +64,16 @@ const matchFilters = (filters: Filters, tokenTransfer: TokenTransfer, address?:

type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
// for tests only
overloadCount?: number;
}

const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender = true }: Props) => {
const router = useRouter();
const queryClient = useQueryClient();
const isMobile = useIsMobile();
const isMounted = useIsMounted();

const currentAddress = getQueryParamString(router.query.hash);

Expand Down Expand Up @@ -179,6 +182,18 @@ const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Pr
handler: handleNewSocketMessage,
});

const tokenData = React.useMemo(() => ({
address: tokenFilter || '',
name: '',
icon_url: '',
symbol: '',
type: 'ERC-20' as const,
}), [ tokenFilter ]);

if (!isMounted || !shouldRender) {
return null;
}

const numActiveFilters = (filters.type?.length || 0) + (filters.filter ? 1 : 0);
const isActionBarHidden = !tokenFilter && !numActiveFilters && !data?.items.length && !currentAddress;

Expand Down Expand Up @@ -218,14 +233,6 @@ const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Pr
</>
) : null;

const tokenData = React.useMemo(() => ({
address: tokenFilter || '',
name: '',
icon_url: '',
symbol: '',
type: 'ERC-20' as const,
}), [ tokenFilter ]);

const tokenFilterComponent = tokenFilter && (
<Flex alignItems="center" flexWrap="wrap" mb={{ base: isActionBarHidden ? 3 : 6, lg: 0 }} mr={ 4 }>
<Text whiteSpace="nowrap" mr={ 2 } py={ 1 }>Filtered by token</Text>
Expand Down
12 changes: 11 additions & 1 deletion ui/address/AddressTokens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useAppContext } from 'lib/contexts/app';
import * as cookies from 'lib/cookies';
import getFilterValuesFromQuery from 'lib/getFilterValuesFromQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
import { ADDRESS_TOKEN_BALANCE_ERC_20, ADDRESS_NFT_1155, ADDRESS_COLLECTION } from 'stubs/address';
Expand Down Expand Up @@ -41,9 +42,14 @@ const TAB_LIST_PROPS_MOBILE = {

const getTokenFilterValue = (getFilterValuesFromQuery<NFTTokenType>).bind(null, NFT_TOKEN_TYPE_IDS);

const AddressTokens = () => {
type Props = {
shouldRender?: boolean;
}

const AddressTokens = ({ shouldRender = true }: Props) => {
const router = useRouter();
const isMobile = useIsMobile();
const isMounted = useIsMounted();

const scrollRef = React.useRef<HTMLDivElement>(null);

Expand Down Expand Up @@ -99,6 +105,10 @@ const AddressTokens = () => {
setTokenTypes(value);
}, [ nftsQuery, collectionsQuery ]);

if (!isMounted || !shouldRender) {
return null;
}

const nftTypeFilter = (
<PopoverFilter isActive={ tokenTypes && tokenTypes.length > 0 } contentProps={{ w: '200px' }} appliedFiltersNum={ tokenTypes?.length }>
<TokenTypeFilter<NFTTokenType> nftOnly onChange={ handleTokenTypesChange } defaultValue={ tokenTypes }/>
Expand Down
9 changes: 8 additions & 1 deletion ui/address/AddressTxs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { Transaction, TransactionsSortingField, TransactionsSortingValue, T
import { getResourceKey } from 'lib/api/useApiQuery';
import getFilterValueFromQuery from 'lib/getFilterValueFromQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
Expand Down Expand Up @@ -47,13 +48,15 @@ const matchFilter = (filterValue: AddressFromToFilter, transaction: Transaction,

type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
// for tests only
overloadCount?: number;
}

const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender = true }: Props) => {
const router = useRouter();
const queryClient = useQueryClient();
const isMounted = useIsMounted();

const [ socketAlert, setSocketAlert ] = React.useState('');
const [ newItemsCount, setNewItemsCount ] = React.useState(0);
Expand Down Expand Up @@ -156,6 +159,10 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
handler: handleNewSocketMessage,
});

if (!isMounted || !shouldRender) {
return null;
}

const filter = (
<AddressTxsFilter
defaultFilter={ filterValue }
Expand Down
9 changes: 8 additions & 1 deletion ui/address/AddressUserOps.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useRouter } from 'next/router';
import React from 'react';

import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import { USER_OPS_ITEM } from 'stubs/userOps';
import { generateListStub } from 'stubs/utils';
Expand All @@ -9,10 +10,12 @@ import UserOpsContent from 'ui/userOps/UserOpsContent';

type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
shouldRender?: boolean;
}

const AddressUserOps = ({ scrollRef }: Props) => {
const AddressUserOps = ({ scrollRef, shouldRender = true }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();

const hash = getQueryParamString(router.query.hash);

Expand All @@ -29,6 +32,10 @@ const AddressUserOps = ({ scrollRef }: Props) => {
filters: { sender: hash },
});

if (!isMounted || !shouldRender) {
return null;
}

return <UserOpsContent query={ userOpsQuery } showSender={ false }/>;
};

Expand Down
Loading

0 comments on commit 57b54a6

Please sign in to comment.