Commit 1fae6db7 authored by isstuev's avatar isstuev

performance improvement on address page

parent 41a982c6
......@@ -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';
......@@ -25,10 +26,12 @@ const getFilterValue = (getFilterValueFromQuery<NovesHistoryFilterValue>).bind(n
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
}
const AddressAccountHistory = ({ scrollRef }: Props) => {
const AddressAccountHistory = ({ scrollRef, isTabsLoading }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();
const currentAddress = getQueryParamString(router.query.hash).toLowerCase();
......@@ -49,6 +52,10 @@ const AddressAccountHistory = ({ scrollRef }: Props) => {
setFilterValue(newVal);
}, [ ]);
if (!isMounted || isTabsLoading) {
return null;
}
const actionBar = (
<ActionBar mt={ -6 } pb={{ base: 6, md: 5 }}>
<AccountHistoryFilter
......
......@@ -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';
......@@ -25,12 +26,14 @@ import AddressBlocksValidatedTableItem from './blocksValidated/AddressBlocksVali
interface Props {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
}
const AddressBlocksValidated = ({ scrollRef }: Props) => {
const AddressBlocksValidated = ({ scrollRef, isTabsLoading }: 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({
......@@ -84,6 +87,10 @@ const AddressBlocksValidated = ({ scrollRef }: Props) => {
handler: handleNewSocketMessage,
});
if (!isMounted || isTabsLoading) {
return null;
}
const content = query.data?.items ? (
<>
{ socketAlert && <SocketAlert mb={ 6 }/> }
......
......@@ -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';
......@@ -17,10 +18,16 @@ import SocketAlert from 'ui/shared/SocketAlert';
import AddressCoinBalanceChart from './coinBalance/AddressCoinBalanceChart';
import AddressCoinBalanceHistory from './coinBalance/AddressCoinBalanceHistory';
const AddressCoinBalance = () => {
type Props = {
isTabsLoading?: boolean;
}
const AddressCoinBalance = ({ isTabsLoading }: 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);
......@@ -78,6 +85,10 @@ const AddressCoinBalance = () => {
handler: handleNewSocketMessage,
});
if (!isMounted || isTabsLoading) {
return null;
}
return (
<>
{ socketAlert && <SocketAlert mb={ 6 }/> }
......
......@@ -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';
......@@ -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)) {
......@@ -74,7 +77,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
const data = addressQuery.isError ? error404Data : addressQuery.data;
if (!data) {
if (!data || !isMounted) {
return null;
}
......
......@@ -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';
......@@ -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>;
isTabsLoading?: boolean;
}
const AddressInternalTxs = ({ scrollRef, isTabsLoading }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();
const [ filterValue, setFilterValue ] = React.useState<AddressFromToFilter>(getFilterValue(router.query.filter));
const hash = getQueryParamString(router.query.hash);
......@@ -55,6 +62,10 @@ const AddressInternalTxs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
onFilterChange({ filter: newVal });
}, [ onFilterChange ]);
if (!isMounted || isTabsLoading) {
return null;
}
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
......
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';
......@@ -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>;
isTabsLoading?: boolean;
}
const AddressLogs = ({ scrollRef, isTabsLoading }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();
const hash = getQueryParamString(router.query.hash);
const { data, isPlaceholderData, isError, pagination } = useQueryWithPages({
......@@ -41,6 +48,10 @@ const AddressLogs = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>
</ActionBar>
);
if (!isMounted || isTabsLoading) {
return null;
}
const content = data?.items ? data.items.map((item, index) => <LogItem key={ index } { ...item } type="address" isLoading={ isPlaceholderData }/>) : null;
return (
......
......@@ -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';
......@@ -63,14 +64,16 @@ const matchFilters = (filters: Filters, tokenTransfer: TokenTransfer, address?:
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
// for tests only
overloadCount?: number;
}
const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT }: Props) => {
const AddressTokenTransfers = ({ scrollRef, overloadCount = OVERLOAD_COUNT, isTabsLoading }: Props) => {
const router = useRouter();
const queryClient = useQueryClient();
const isMobile = useIsMobile();
const isMounted = useIsMounted();
const currentAddress = getQueryParamString(router.query.hash);
......@@ -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 || isTabsLoading) {
return null;
}
const numActiveFilters = (filters.type?.length || 0) + (filters.filter ? 1 : 0);
const isActionBarHidden = !tokenFilter && !numActiveFilters && !data?.items.length && !currentAddress;
......@@ -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>
......
......@@ -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';
......@@ -41,9 +42,14 @@ const TAB_LIST_PROPS_MOBILE = {
const getTokenFilterValue = (getFilterValuesFromQuery<NFTTokenType>).bind(null, NFT_TOKEN_TYPE_IDS);
const AddressTokens = () => {
type Props = {
isTabsLoading?: boolean;
}
const AddressTokens = ({ isTabsLoading }: Props) => {
const router = useRouter();
const isMobile = useIsMobile();
const isMounted = useIsMounted();
const scrollRef = React.useRef<HTMLDivElement>(null);
......@@ -99,6 +105,10 @@ const AddressTokens = () => {
setTokenTypes(value);
}, [ nftsQuery, collectionsQuery ]);
if (!isMounted || isTabsLoading) {
return null;
}
const nftTypeFilter = (
<PopoverFilter isActive={ tokenTypes && tokenTypes.length > 0 } contentProps={{ w: '200px' }} appliedFiltersNum={ tokenTypes?.length }>
<TokenTypeFilter<NFTTokenType> nftOnly onChange={ handleTokenTypesChange } defaultValue={ tokenTypes }/>
......
......@@ -48,12 +48,12 @@ const matchFilter = (filterValue: AddressFromToFilter, transaction: Transaction,
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
// for tests only
overloadCount?: number;
onLoad?: () => void;
}
const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, onLoad }: Props) => {
const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, isTabsLoading }: Props) => {
const router = useRouter();
const queryClient = useQueryClient();
const isMounted = useIsMounted();
......@@ -82,12 +82,6 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, onLoad }: Props
},
});
React.useEffect(() => {
if (!addressTxsQuery.isPlaceholderData) {
onLoad?.();
}
}, [ addressTxsQuery.isPlaceholderData, onLoad ]);
const handleFilterChange = React.useCallback((val: string | Array<string>) => {
const newVal = getFilterValue(val);
......@@ -165,7 +159,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, onLoad }: Props
handler: handleNewSocketMessage,
});
if (!isMounted) {
if (!isMounted || isTabsLoading) {
return null;
}
......
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';
......@@ -9,10 +10,12 @@ import UserOpsContent from 'ui/userOps/UserOpsContent';
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
}
const AddressUserOps = ({ scrollRef }: Props) => {
const AddressUserOps = ({ scrollRef, isTabsLoading }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();
const hash = getQueryParamString(router.query.hash);
......@@ -29,6 +32,10 @@ const AddressUserOps = ({ scrollRef }: Props) => {
filters: { sender: hash },
});
if (!isMounted || isTabsLoading) {
return null;
}
return <UserOpsContent query={ userOpsQuery } showSender={ false }/>;
};
......
......@@ -2,6 +2,7 @@ import { Show, Hide } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';
import useIsMounted from 'lib/hooks/useIsMounted';
import getQueryParamString from 'lib/router/getQueryParamString';
import { generateListStub } from 'stubs/utils';
import { WITHDRAWAL } from 'stubs/withdrawals';
......@@ -12,8 +13,13 @@ import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import BeaconChainWithdrawalsListItem from 'ui/withdrawals/beaconChain/BeaconChainWithdrawalsListItem';
import BeaconChainWithdrawalsTable from 'ui/withdrawals/beaconChain/BeaconChainWithdrawalsTable';
const AddressWithdrawals = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivElement>}) => {
type Props = {
scrollRef?: React.RefObject<HTMLDivElement>;
isTabsLoading?: boolean;
}
const AddressWithdrawals = ({ scrollRef, isTabsLoading }: Props) => {
const router = useRouter();
const isMounted = useIsMounted();
const hash = getQueryParamString(router.query.hash);
......@@ -28,6 +34,11 @@ const AddressWithdrawals = ({ scrollRef }: {scrollRef?: React.RefObject<HTMLDivE
} }),
},
});
if (!isMounted || isTabsLoading) {
return null;
}
const content = data?.items ? (
<>
<Show below="lg" ssr={ false }>
......
import { Box, Flex, HStack, useColorModeValue } from '@chakra-ui/react';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -17,7 +16,7 @@ import AddressAccountHistory from 'ui/address/AddressAccountHistory';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance';
import AddressContract from 'ui/address/AddressContract';
// import AddressDetails from 'ui/address/AddressDetails';
import AddressDetails from 'ui/address/AddressDetails';
import AddressInternalTxs from 'ui/address/AddressInternalTxs';
import AddressLogs from 'ui/address/AddressLogs';
import AddressTokens from 'ui/address/AddressTokens';
......@@ -41,8 +40,6 @@ import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
const AddressDetails = dynamic(() => import('ui/address/AddressDetails'), { ssr: false });
const TOKEN_TABS = [ 'tokens_erc20', 'tokens_nfts', 'tokens_nfts_collection', 'tokens_nfts_list' ];
const txInterpretation = config.features.txInterpretation;
......@@ -77,19 +74,22 @@ const AddressPageContent = () => {
const contractTabs = useContractTabs(addressQuery.data);
const isLoading = addressQuery.isPlaceholderData || (config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData);
const isTabsLoading = isLoading || addressTabsCountersQuery.isPlaceholderData;
const tabs: Array<RoutedTab> = React.useMemo(() => {
return [
{
id: 'txs',
title: 'Transactions',
count: addressTabsCountersQuery.data?.transactions_count,
component: ({ onLoad }: { onLoad: () => void }) => <AddressTxs scrollRef={ tabsScrollRef } onLoad={ onLoad }/>,
component: <AddressTxs scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
},
txInterpretation.isEnabled && txInterpretation.provider === 'noves' ?
{
id: 'account_history',
title: 'Account history',
component: <AddressAccountHistory scrollRef={ tabsScrollRef }/>,
component: <AddressAccountHistory scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
} :
undefined,
config.features.userOps.isEnabled && Boolean(userOpsAccountQuery.data?.total_ops) ?
......@@ -97,7 +97,7 @@ const AddressPageContent = () => {
id: 'user_ops',
title: 'User operations',
count: userOpsAccountQuery.data?.total_ops,
component: <AddressUserOps/>,
component: <AddressUserOps isTabsLoading={ isTabsLoading }/>,
} :
undefined,
config.features.beaconChain.isEnabled && addressTabsCountersQuery.data?.withdrawals_count ?
......@@ -105,39 +105,39 @@ const AddressPageContent = () => {
id: 'withdrawals',
title: 'Withdrawals',
count: addressTabsCountersQuery.data?.withdrawals_count,
component: <AddressWithdrawals scrollRef={ tabsScrollRef }/>,
component: <AddressWithdrawals scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
} :
undefined,
{
id: 'token_transfers',
title: 'Token transfers',
count: addressTabsCountersQuery.data?.token_transfers_count,
component: <AddressTokenTransfers scrollRef={ tabsScrollRef }/>,
component: <AddressTokenTransfers scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
},
{
id: 'tokens',
title: 'Tokens',
count: addressTabsCountersQuery.data?.token_balances_count,
component: <AddressTokens/>,
component: <AddressTokens isTabsLoading={ isTabsLoading }/>,
subTabs: TOKEN_TABS,
},
{
id: 'internal_txns',
title: 'Internal txns',
count: addressTabsCountersQuery.data?.internal_txs_count,
component: <AddressInternalTxs scrollRef={ tabsScrollRef }/>,
component: <AddressInternalTxs scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
},
{
id: 'coin_balance_history',
title: 'Coin balance history',
component: <AddressCoinBalance/>,
component: <AddressCoinBalance isTabsLoading={ isTabsLoading }/>,
},
config.chain.verificationType === 'validation' && addressTabsCountersQuery.data?.validations_count ?
{
id: 'blocks_validated',
title: 'Blocks validated',
count: addressTabsCountersQuery.data?.validations_count,
component: <AddressBlocksValidated scrollRef={ tabsScrollRef }/>,
component: <AddressBlocksValidated scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
} :
undefined,
addressTabsCountersQuery.data?.logs_count ?
......@@ -145,9 +145,10 @@ const AddressPageContent = () => {
id: 'logs',
title: 'Logs',
count: addressTabsCountersQuery.data?.logs_count,
component: <AddressLogs scrollRef={ tabsScrollRef }/>,
component: <AddressLogs scrollRef={ tabsScrollRef } isTabsLoading={ isTabsLoading }/>,
} :
undefined,
addressQuery.data?.is_contract ? {
id: 'contract',
title: () => {
......@@ -166,9 +167,7 @@ const AddressPageContent = () => {
subTabs: contractTabs.map(tab => tab.id),
} : undefined,
].filter(Boolean);
}, [ addressQuery.data, contractTabs, addressTabsCountersQuery.data, userOpsAccountQuery.data ]);
const isLoading = addressQuery.isPlaceholderData || (config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData);
}, [ addressQuery.data, contractTabs, addressTabsCountersQuery.data, userOpsAccountQuery.data, isTabsLoading ]);
const tags = (
<EntityTags
......@@ -185,7 +184,9 @@ const AddressPageContent = () => {
/>
);
const content = (addressQuery.isError || addressQuery.isDegradedData) ? null : <RoutedTabs tabs={ tabs } tabListProps={{ mt: 8 }}/>;
const content = (addressQuery.isError || addressQuery.isDegradedData) ?
null :
<RoutedTabs tabs={ tabs } tabListProps={{ mt: 8 }} isLoading={ isLoading || addressTabsCountersQuery.isPlaceholderData }/>;
const backLink = React.useMemo(() => {
const hasGoBackLink = appProps.referrer && appProps.referrer.includes('/accounts');
......
......@@ -24,7 +24,7 @@ interface Props extends TabsProps {
activeTabIndex: number;
onItemClick: (index: number) => void;
themeProps: ThemingProps<'Tabs'>;
isLoading: boolean;
isLoading?: boolean;
}
const AdaptiveTabsList = (props: Props) => {
......
......@@ -17,9 +17,10 @@ interface Props extends ThemingProps<'Tabs'> {
stickyEnabled?: boolean;
className?: string;
onTabChange?: (index: number) => void;
isLoading?: boolean;
}
const RoutedTabs = ({ tabs, tabListProps, rightSlot, rightSlotProps, stickyEnabled, className, onTabChange, ...themeProps }: Props) => {
const RoutedTabs = ({ tabs, tabListProps, rightSlot, rightSlotProps, stickyEnabled, className, onTabChange, isLoading, ...themeProps }: Props) => {
const router = useRouter();
const tabIndex = useTabIndexFromQuery(tabs);
const tabsRef = useRef<HTMLDivElement>(null);
......@@ -63,6 +64,7 @@ const RoutedTabs = ({ tabs, tabListProps, rightSlot, rightSlotProps, stickyEnabl
stickyEnabled={ stickyEnabled }
onTabChange={ handleTabChange }
defaultTabIndex={ tabIndex }
isLoading={ isLoading }
{ ...themeProps }
/>
);
......
......@@ -25,6 +25,7 @@ export interface Props extends ThemingProps<'Tabs'> {
stickyEnabled?: boolean;
onTabChange?: (index: number) => void;
defaultTabIndex?: number;
isLoading?: boolean;
className?: string;
}
......@@ -37,12 +38,12 @@ const TabsWithScroll = ({
stickyEnabled,
onTabChange,
defaultTabIndex,
isLoading,
className,
...themeProps
}: Props) => {
const [ activeTabIndex, setActiveTabIndex ] = useState<number>(defaultTabIndex || 0);
const [ screenWidth, setScreenWidth ] = React.useState(isBrowser() ? window.innerWidth : 0);
const [ isLoading, setIsLoading ] = React.useState(true);
const tabsRef = useRef<HTMLDivElement>(null);
......@@ -72,20 +73,8 @@ const TabsWithScroll = ({
};
}, []);
const handleLoad = React.useCallback(() => {
setIsLoading(false);
}, []);
const renderContent = React.useCallback((component: TabItem['component']) => {
if (typeof component === 'function') {
return component({ onLoad: handleLoad });
}
return component;
}, [ handleLoad ]);
if (tabs.length === 1) {
return <div>{ renderContent(tabs[0].component) }</div>;
return <div>{ tabs[0].component }</div>;
}
return (
......@@ -117,7 +106,7 @@ const TabsWithScroll = ({
isLoading={ isLoading }
/>
<TabPanels>
{ tabsList.map((tab) => <TabPanel padding={ 0 } key={ tab.id }>{ renderContent(tab.component) }</TabPanel>) }
{ tabsList.map((tab) => <TabPanel padding={ 0 } key={ tab.id }>{ tab.component }</TabPanel>) }
</TabPanels>
</Tabs>
);
......
......@@ -4,7 +4,7 @@ export interface TabItem {
id: string;
title: string | (() => React.ReactNode);
count?: number | null;
component: React.ReactNode | (({ onLoad }: { onLoad: () => void }) => React.ReactNode);
component: React.ReactNode;
}
export type RoutedTab = TabItem & { subTabs?: Array<string> }
......
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