Commit 139721ee authored by tom goriunov's avatar tom goriunov Committed by GitHub

migrate to ReactQuery v5 (#1321)

* change signature of hooks

* isLoading -> isPending

* default error type

* dev tools props
parent 3846c3bd
...@@ -20,6 +20,7 @@ module.exports = { ...@@ -20,6 +20,7 @@ module.exports = {
'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/recommended',
'plugin:jest/recommended', 'plugin:jest/recommended',
'plugin:playwright/playwright-test', 'plugin:playwright/playwright-test',
'plugin:@tanstack/eslint-plugin-query/recommended',
], ],
plugins: [ plugins: [
'es5', 'es5',
...@@ -31,6 +32,7 @@ module.exports = { ...@@ -31,6 +32,7 @@ module.exports = {
'eslint-plugin-import-helpers', 'eslint-plugin-import-helpers',
'jest', 'jest',
'eslint-plugin-no-cyrillic-string', 'eslint-plugin-no-cyrillic-string',
'@tanstack/query',
], ],
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
......
...@@ -23,12 +23,15 @@ export default function useApiQuery<R extends ResourceName, E = unknown>( ...@@ -23,12 +23,15 @@ export default function useApiQuery<R extends ResourceName, E = unknown>(
) { ) {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
return useQuery<ResourcePayload<R>, ResourceError<E>, ResourcePayload<R>>( return useQuery<ResourcePayload<R>, ResourceError<E>, ResourcePayload<R>>({
getResourceKey(resource, { pathParams, queryParams }), // eslint-disable-next-line @tanstack/query/exhaustive-deps
async() => { queryKey: getResourceKey(resource, { pathParams, queryParams }),
queryFn: async() => {
// all errors and error typing is handled by react-query // all errors and error typing is handled by react-query
// so error response will never go to the data // so error response will never go to the data
// that's why we are safe here to do type conversion "as Promise<ResourcePayload<R>>" // that's why we are safe here to do type conversion "as Promise<ResourcePayload<R>>"
return apiFetch(resource, { pathParams, queryParams, fetchParams }) as Promise<ResourcePayload<R>>; return apiFetch(resource, { pathParams, queryParams, fetchParams }) as Promise<ResourcePayload<R>>;
}, queryOptions); },
...queryOptions,
});
} }
...@@ -18,7 +18,7 @@ export default function useQueryClientConfig() { ...@@ -18,7 +18,7 @@ export default function useQueryClientConfig() {
} }
return failureCount < 2; return failureCount < 2;
}, },
useErrorBoundary: (error) => { throwOnError: (error) => {
const status = getErrorObjStatusCode(error); const status = getErrorObjStatusCode(error);
// don't catch error for "Too many requests" response // don't catch error for "Too many requests" response
return status === 429; return status === 429;
......
...@@ -10,27 +10,29 @@ import useFetch from 'lib/hooks/useFetch'; ...@@ -10,27 +10,29 @@ import useFetch from 'lib/hooks/useFetch';
export default function useGetCsrfToken() { export default function useGetCsrfToken() {
const nodeApiFetch = useFetch(); const nodeApiFetch = useFetch();
useQuery(getResourceKey('csrf'), async() => { useQuery({
if (!isNeedProxy()) { queryKey: getResourceKey('csrf'),
const url = buildUrl('csrf'); queryFn: async() => {
const apiResponse = await fetch(url, { credentials: 'include' }); if (!isNeedProxy()) {
const csrfFromHeader = apiResponse.headers.get('x-bs-account-csrf'); const url = buildUrl('csrf');
const apiResponse = await fetch(url, { credentials: 'include' });
const csrfFromHeader = apiResponse.headers.get('x-bs-account-csrf');
if (!csrfFromHeader) { if (!csrfFromHeader) {
Sentry.captureException(new Error('Client fetch failed'), { tags: { Sentry.captureException(new Error('Client fetch failed'), { tags: {
source: 'fetch', source: 'fetch',
'source.resource': 'csrf', 'source.resource': 'csrf',
'status.code': 500, 'status.code': 500,
'status.text': 'Unable to obtain csrf token from header', 'status.text': 'Unable to obtain csrf token from header',
} }); } });
return; return;
} }
return { token: csrfFromHeader }; return { token: csrfFromHeader };
} }
return nodeApiFetch('/node-api/csrf'); return nodeApiFetch('/node-api/csrf');
}, { },
enabled: Boolean(cookies.get(cookies.NAMES.API_TOKEN)), enabled: Boolean(cookies.get(cookies.NAMES.API_TOKEN)),
}); });
} }
...@@ -8,20 +8,18 @@ const feature = config.features.safe; ...@@ -8,20 +8,18 @@ const feature = config.features.safe;
export default function useIsSafeAddress(hash: string | undefined): boolean { export default function useIsSafeAddress(hash: string | undefined): boolean {
const fetch = useFetch(); const fetch = useFetch();
const { data } = useQuery( const { data } = useQuery({
[ 'safe_transaction_api', hash ], queryKey: [ 'safe_transaction_api', hash ],
async() => { queryFn: async() => {
if (!feature.isEnabled || !hash) { if (!feature.isEnabled || !hash) {
return Promise.reject(); return Promise.reject();
} }
return fetch(`${ feature.apiUrl }/${ hash }`, undefined, { omitSentryErrorLog: true }); return fetch(`${ feature.apiUrl }/${ hash }`, undefined, { omitSentryErrorLog: true });
}, },
{ enabled: feature.isEnabled && Boolean(hash),
enabled: feature.isEnabled && Boolean(hash), refetchOnMount: false,
refetchOnMount: false, });
},
);
return Boolean(data); return Boolean(data);
} }
...@@ -59,7 +59,7 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) { ...@@ -59,7 +59,7 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
{ getLayout(<Component { ...pageProps }/>) } { getLayout(<Component { ...pageProps }/>) }
</SocketProvider> </SocketProvider>
</ScrollDirectionProvider> </ScrollDirectionProvider>
<ReactQueryDevtools/> <ReactQueryDevtools buttonPosition="bottom-left" position="left"/>
<GoogleAnalytics/> <GoogleAnalytics/>
</QueryClientProvider> </QueryClientProvider>
</AppContextProvider> </AppContextProvider>
......
...@@ -10,7 +10,7 @@ interface Props { ...@@ -10,7 +10,7 @@ interface Props {
} }
const AddressCoinBalanceChart = ({ addressHash }: Props) => { const AddressCoinBalanceChart = ({ addressHash }: Props) => {
const { data, isLoading, isError } = useApiQuery('address_coin_balance_chart', { const { data, isPending, isError } = useApiQuery('address_coin_balance_chart', {
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
}); });
...@@ -24,7 +24,7 @@ const AddressCoinBalanceChart = ({ addressHash }: Props) => { ...@@ -24,7 +24,7 @@ const AddressCoinBalanceChart = ({ addressHash }: Props) => {
isError={ isError } isError={ isError }
title="Balances" title="Balances"
items={ items } items={ items }
isLoading={ isLoading } isLoading={ isPending }
h="300px" h="300px"
units={ config.chain.currency.symbol } units={ config.chain.currency.symbol }
/> />
......
...@@ -6,6 +6,7 @@ import type { AddressCoinBalanceHistoryResponse } from 'types/api/address'; ...@@ -6,6 +6,7 @@ import type { AddressCoinBalanceHistoryResponse } from 'types/api/address';
import type { PaginationParams } from 'ui/shared/pagination/types'; import type { PaginationParams } from 'ui/shared/pagination/types';
import config from 'configs/app'; import config from 'configs/app';
import type { ResourceError } from 'lib/api/resources';
import ActionBar from 'ui/shared/ActionBar'; import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay'; import DataListDisplay from 'ui/shared/DataListDisplay';
import Pagination from 'ui/shared/pagination/Pagination'; import Pagination from 'ui/shared/pagination/Pagination';
...@@ -15,7 +16,7 @@ import AddressCoinBalanceListItem from './AddressCoinBalanceListItem'; ...@@ -15,7 +16,7 @@ import AddressCoinBalanceListItem from './AddressCoinBalanceListItem';
import AddressCoinBalanceTableItem from './AddressCoinBalanceTableItem'; import AddressCoinBalanceTableItem from './AddressCoinBalanceTableItem';
interface Props { interface Props {
query: UseQueryResult<AddressCoinBalanceHistoryResponse> & { query: UseQueryResult<AddressCoinBalanceHistoryResponse, ResourceError<unknown>> & {
pagination: PaginationParams; pagination: PaginationParams;
}; };
} }
......
...@@ -27,7 +27,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -27,7 +27,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const account = useWatchAccount(); const account = useWatchAccount();
const { data, isLoading, isError } = useApiQuery(isProxy ? 'contract_methods_read_proxy' : 'contract_methods_read', { const { data, isPending, isError } = useApiQuery(isProxy ? 'contract_methods_read_proxy' : 'contract_methods_read', {
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
queryParams: { queryParams: {
is_custom_abi: isCustomAbi ? 'true' : 'false', is_custom_abi: isCustomAbi ? 'true' : 'false',
...@@ -83,7 +83,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -83,7 +83,7 @@ const ContractRead = ({ addressHash, isProxy, isCustomAbi }: Props) => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (isLoading) { if (isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -29,7 +29,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -29,7 +29,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => {
const { chain } = useNetwork(); const { chain } = useNetwork();
const { switchNetworkAsync } = useSwitchNetwork(); const { switchNetworkAsync } = useSwitchNetwork();
const { data, isLoading, isError } = useApiQuery(isProxy ? 'contract_methods_write_proxy' : 'contract_methods_write', { const { data, isPending, isError } = useApiQuery(isProxy ? 'contract_methods_write_proxy' : 'contract_methods_write', {
pathParams: { hash: addressHash }, pathParams: { hash: addressHash },
queryParams: { queryParams: {
is_custom_abi: isCustomAbi ? 'true' : 'false', is_custom_abi: isCustomAbi ? 'true' : 'false',
...@@ -99,7 +99,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => { ...@@ -99,7 +99,7 @@ const ContractWrite = ({ addressHash, isProxy, isCustomAbi }: Props) => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (isLoading) { if (isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -7,11 +7,12 @@ import type { AddressCounters } from 'types/api/address'; ...@@ -7,11 +7,12 @@ import type { AddressCounters } from 'types/api/address';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources';
import LinkInternal from 'ui/shared/LinkInternal'; import LinkInternal from 'ui/shared/LinkInternal';
interface Props { interface Props {
prop: keyof AddressCounters; prop: keyof AddressCounters;
query: UseQueryResult<AddressCounters>; query: UseQueryResult<AddressCounters, ResourceError<unknown>>;
address: string; address: string;
onClick: () => void; onClick: () => void;
isAddressQueryLoading: boolean; isAddressQueryLoading: boolean;
......
...@@ -35,7 +35,7 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -35,7 +35,7 @@ const TokenSelect = ({ onClick }: Props) => {
const addressQueryData = queryClient.getQueryData<Address>(addressResourceKey); const addressQueryData = queryClient.getQueryData<Address>(addressResourceKey);
const { data, isError, isLoading, refetch } = useFetchTokens({ hash: addressQueryData?.hash }); const { data, isError, isPending, refetch } = useFetchTokens({ hash: addressQueryData?.hash });
const tokensResourceKey = getResourceKey('address_tokens', { pathParams: { hash: addressQueryData?.hash }, queryParams: { type: 'ERC-20' } }); const tokensResourceKey = getResourceKey('address_tokens', { pathParams: { hash: addressQueryData?.hash }, queryParams: { type: 'ERC-20' } });
const tokensIsFetching = useIsFetching({ queryKey: tokensResourceKey }); const tokensIsFetching = useIsFetching({ queryKey: tokensResourceKey });
...@@ -72,7 +72,7 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -72,7 +72,7 @@ const TokenSelect = ({ onClick }: Props) => {
handler: handleTokenBalanceMessage, handler: handleTokenBalanceMessage,
}); });
if (isLoading) { if (isPending) {
return ( return (
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton h={ 8 } w="150px" borderRadius="base"/> <Skeleton h={ 8 } w="150px" borderRadius="base"/>
......
...@@ -49,12 +49,12 @@ const TokenBalances = () => { ...@@ -49,12 +49,12 @@ const TokenBalances = () => {
<TokenBalancesItem <TokenBalancesItem
name="Net Worth" name="Net Worth"
value={ addressData?.exchange_rate ? `${ prefix }$${ totalUsd.toFormat(2) } USD` : 'N/A' } value={ addressData?.exchange_rate ? `${ prefix }$${ totalUsd.toFormat(2) } USD` : 'N/A' }
isLoading={ addressQuery.isLoading || tokenQuery.isLoading } isLoading={ addressQuery.isPending || tokenQuery.isPending }
/> />
<TokenBalancesItem <TokenBalancesItem
name={ `${ config.chain.currency.symbol } Balance` } name={ `${ config.chain.currency.symbol } Balance` }
value={ (!nativeUsd.eq(ZERO) ? `$${ nativeUsd.toFormat(2) } USD | ` : '') + `${ nativeValue } ${ config.chain.currency.symbol }` } value={ (!nativeUsd.eq(ZERO) ? `$${ nativeUsd.toFormat(2) } USD | ` : '') + `${ nativeValue } ${ config.chain.currency.symbol }` }
isLoading={ addressQuery.isLoading || tokenQuery.isLoading } isLoading={ addressQuery.isPending || tokenQuery.isPending }
/> />
<TokenBalancesItem <TokenBalancesItem
name="Tokens" name="Tokens"
...@@ -62,7 +62,7 @@ const TokenBalances = () => { ...@@ -62,7 +62,7 @@ const TokenBalances = () => {
`${ prefix }$${ tokensInfo.usd.toFormat(2) } USD ` + `${ prefix }$${ tokensInfo.usd.toFormat(2) } USD ` +
tokensNumText tokensNumText
} }
isLoading={ addressQuery.isLoading || tokenQuery.isLoading } isLoading={ addressQuery.isPending || tokenQuery.isPending }
/> />
</Flex> </Flex>
); );
......
...@@ -49,7 +49,7 @@ export default function useFetchTokens({ hash }: Props) { ...@@ -49,7 +49,7 @@ export default function useFetchTokens({ hash }: Props) {
}, [ erc1155query.data, erc20query.data, erc721query.data ]); }, [ erc1155query.data, erc20query.data, erc721query.data ]);
return { return {
isLoading: erc20query.isLoading || erc721query.isLoading || erc1155query.isLoading, isPending: erc20query.isPending || erc721query.isPending || erc1155query.isPending,
isError: erc20query.isError || erc721query.isError || erc1155query.isError, isError: erc20query.isError || erc721query.isError || erc1155query.isError,
data, data,
refetch, refetch,
......
...@@ -57,7 +57,8 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => { ...@@ -57,7 +57,8 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
}); });
}; };
const mutation = useMutation(updateApiKey, { const mutation = useMutation({
mutationFn: updateApiKey,
onSuccess: async(data) => { onSuccess: async(data) => {
const response = data as unknown as ApiKey; const response = data as unknown as ApiKey;
...@@ -148,7 +149,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => { ...@@ -148,7 +149,7 @@ const ApiKeyForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
size="lg" size="lg"
type="submit" type="submit"
isDisabled={ !isDirty } isDisabled={ !isDirty }
isLoading={ mutation.isLoading } isLoading={ mutation.isPending }
> >
{ data ? 'Save' : 'Generate API key' } { data ? 'Save' : 'Generate API key' }
</Button> </Button>
......
...@@ -21,7 +21,7 @@ const hooksConfig = { ...@@ -21,7 +21,7 @@ const hooksConfig = {
test('regular block +@mobile +@dark-mode', async({ mount, page }) => { test('regular block +@mobile +@dark-mode', async({ mount, page }) => {
const query = { const query = {
data: blockMock.base, data: blockMock.base,
isLoading: false, isPending: false,
} as UseQueryResult<Block, ResourceError>; } as UseQueryResult<Block, ResourceError>;
const component = await mount( const component = await mount(
...@@ -39,7 +39,7 @@ test('regular block +@mobile +@dark-mode', async({ mount, page }) => { ...@@ -39,7 +39,7 @@ test('regular block +@mobile +@dark-mode', async({ mount, page }) => {
test('genesis block', async({ mount, page }) => { test('genesis block', async({ mount, page }) => {
const query = { const query = {
data: blockMock.genesis, data: blockMock.genesis,
isLoading: false, isPending: false,
} as UseQueryResult<Block, ResourceError>; } as UseQueryResult<Block, ResourceError>;
const component = await mount( const component = await mount(
...@@ -62,7 +62,7 @@ const customFieldsTest = test.extend({ ...@@ -62,7 +62,7 @@ const customFieldsTest = test.extend({
customFieldsTest('rootstock custom fields', async({ mount, page }) => { customFieldsTest('rootstock custom fields', async({ mount, page }) => {
const query = { const query = {
data: blockMock.rootstock, data: blockMock.rootstock,
isLoading: false, isPending: false,
} as UseQueryResult<Block, ResourceError>; } as UseQueryResult<Block, ResourceError>;
const component = await mount( const component = await mount(
......
...@@ -63,7 +63,8 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => { ...@@ -63,7 +63,8 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
const formBackgroundColor = useColorModeValue('white', 'gray.900'); const formBackgroundColor = useColorModeValue('white', 'gray.900');
const mutation = useMutation(customAbiKey, { const mutation = useMutation({
mutationFn: customAbiKey,
onSuccess: (data) => { onSuccess: (data) => {
const response = data as unknown as CustomAbi; const response = data as unknown as CustomAbi;
queryClient.setQueryData([ resourceKey('custom_abi') ], (prevData: CustomAbis | undefined) => { queryClient.setQueryData([ resourceKey('custom_abi') ], (prevData: CustomAbis | undefined) => {
...@@ -175,7 +176,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => { ...@@ -175,7 +176,7 @@ const CustomAbiForm: React.FC<Props> = ({ data, onClose, setAlertVisible }) => {
size="lg" size="lg"
type="submit" type="submit"
isDisabled={ !isDirty } isDisabled={ !isDirty }
isLoading={ mutation.isLoading } isLoading={ mutation.isPending }
> >
{ data ? 'Save' : 'Create custom ABI' } { data ? 'Save' : 'Create custom ABI' }
</Button> </Button>
......
...@@ -11,10 +11,10 @@ import ChainIndicatorChart from './ChainIndicatorChart'; ...@@ -11,10 +11,10 @@ import ChainIndicatorChart from './ChainIndicatorChart';
type Props = UseQueryResult<TimeChartData>; type Props = UseQueryResult<TimeChartData>;
const ChainIndicatorChartContainer = ({ data, isError, isLoading }: Props) => { const ChainIndicatorChartContainer = ({ data, isError, isPending }: Props) => {
const content = (() => { const content = (() => {
if (isLoading) { if (isPending) {
return <ContentLoader mt="auto"/>; return <ContentLoader mt="auto"/>;
} }
......
...@@ -5,6 +5,7 @@ import React from 'react'; ...@@ -5,6 +5,7 @@ import React from 'react';
import type { HomeStats } from 'types/api/stats'; import type { HomeStats } from 'types/api/stats';
import type { ChainIndicatorId } from 'types/homepage'; import type { ChainIndicatorId } from 'types/homepage';
import type { ResourceError } from 'lib/api/resources';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
interface Props { interface Props {
...@@ -14,7 +15,7 @@ interface Props { ...@@ -14,7 +15,7 @@ interface Props {
icon: React.ReactNode; icon: React.ReactNode;
isSelected: boolean; isSelected: boolean;
onClick: (id: ChainIndicatorId) => void; onClick: (id: ChainIndicatorId) => void;
stats: UseQueryResult<HomeStats>; stats: UseQueryResult<HomeStats, ResourceError<unknown>>;
} }
const ChainIndicatorItem = ({ id, title, value, icon, isSelected, onClick, stats }: Props) => { const ChainIndicatorItem = ({ id, title, value, icon, isSelected, onClick, stats }: Props) => {
...@@ -33,7 +34,7 @@ const ChainIndicatorItem = ({ id, title, value, icon, isSelected, onClick, stats ...@@ -33,7 +34,7 @@ const ChainIndicatorItem = ({ id, title, value, icon, isSelected, onClick, stats
return null; return null;
} }
if (stats.isLoading) { if (stats.isPending) {
return ( return (
<Skeleton <Skeleton
h={ 3 } h={ 3 }
......
...@@ -41,7 +41,7 @@ const ChainIndicators = () => { ...@@ -41,7 +41,7 @@ const ChainIndicators = () => {
} }
const valueTitle = (() => { const valueTitle = (() => {
if (statsQueryResult.isLoading) { if (statsQueryResult.isPending) {
return <Skeleton h="48px" w="215px" mt={ 3 } mb={ 4 }/>; return <Skeleton h="48px" w="215px" mt={ 3 } mb={ 4 }/>;
} }
......
...@@ -24,15 +24,14 @@ function isAppCategoryMatches(category: string, app: MarketplaceAppOverview, fav ...@@ -24,15 +24,14 @@ function isAppCategoryMatches(category: string, app: MarketplaceAppOverview, fav
export default function useMarketplaceApps(filter: string, selectedCategoryId: string = MarketplaceCategory.ALL, favoriteApps: Array<string> = []) { export default function useMarketplaceApps(filter: string, selectedCategoryId: string = MarketplaceCategory.ALL, favoriteApps: Array<string> = []) {
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const { isPlaceholderData, isError, error, data } = useQuery<unknown, ResourceError<unknown>, Array<MarketplaceAppOverview>>( const { isPlaceholderData, isError, error, data } = useQuery<unknown, ResourceError<unknown>, Array<MarketplaceAppOverview>>({
[ 'marketplace-apps' ], queryKey: [ 'marketplace-apps' ],
async() => apiFetch(configUrl, undefined, { resource: 'marketplace-apps' }), queryFn: async() => apiFetch(configUrl, undefined, { resource: 'marketplace-apps' }),
{ select: (data) => (data as Array<MarketplaceAppOverview>).sort((a, b) => a.title.localeCompare(b.title)),
select: (data) => (data as Array<MarketplaceAppOverview>).sort((a, b) => a.title.localeCompare(b.title)), placeholderData: feature.isEnabled ? Array(9).fill(MARKETPLACE_APP) : undefined,
placeholderData: feature.isEnabled ? Array(9).fill(MARKETPLACE_APP) : undefined, staleTime: Infinity,
staleTime: Infinity, enabled: feature.isEnabled,
enabled: feature.isEnabled, });
});
const displayedApps = React.useMemo(() => { const displayedApps = React.useMemo(() => {
return data?.filter(app => isAppNameMatches(filter, app) && isAppCategoryMatches(selectedCategoryId, app, favoriteApps)) || []; return data?.filter(app => isAppNameMatches(filter, app) && isAppCategoryMatches(selectedCategoryId, app, favoriteApps)) || [];
......
...@@ -64,7 +64,7 @@ const ContractVerification = () => { ...@@ -64,7 +64,7 @@ const ContractVerification = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (configQuery.isLoading || contractQuery.isLoading || isVerifiedContract) { if (configQuery.isPending || contractQuery.isPending || isVerifiedContract) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -108,7 +108,7 @@ const CsvExport = () => { ...@@ -108,7 +108,7 @@ const CsvExport = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (addressQuery.isLoading) { if (addressQuery.isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -34,9 +34,9 @@ const MarketplaceApp = () => { ...@@ -34,9 +34,9 @@ const MarketplaceApp = () => {
const router = useRouter(); const router = useRouter();
const id = getQueryParamString(router.query.id); const id = getQueryParamString(router.query.id);
const { isLoading, isError, error, data } = useQuery<unknown, ResourceError<unknown>, MarketplaceAppOverview>( const { isPending, isError, error, data } = useQuery<unknown, ResourceError<unknown>, MarketplaceAppOverview>({
[ 'marketplace-apps', id ], queryKey: [ 'marketplace-apps', id ],
async() => { queryFn: async() => {
const result = await apiFetch<Array<MarketplaceAppOverview>, unknown>(configUrl, undefined, { resource: 'marketplace-apps' }); const result = await apiFetch<Array<MarketplaceAppOverview>, unknown>(configUrl, undefined, { resource: 'marketplace-apps' });
if (!Array.isArray(result)) { if (!Array.isArray(result)) {
throw result; throw result;
...@@ -49,12 +49,10 @@ const MarketplaceApp = () => { ...@@ -49,12 +49,10 @@ const MarketplaceApp = () => {
return item; return item;
}, },
{ enabled: feature.isEnabled,
enabled: feature.isEnabled, });
},
);
const [ isFrameLoading, setIsFrameLoading ] = useState(isLoading); const [ isFrameLoading, setIsFrameLoading ] = useState(isPending);
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const handleIframeLoad = useCallback(() => { const handleIframeLoad = useCallback(() => {
...@@ -106,7 +104,7 @@ const MarketplaceApp = () => { ...@@ -106,7 +104,7 @@ const MarketplaceApp = () => {
return ( return (
<> <>
{ !isLoading && <PageTitle title={ data.title } backLink={ backLink }/> } { !isPending && <PageTitle title={ data.title } backLink={ backLink }/> }
<Center <Center
h="100vh" h="100vh"
mx={{ base: -4, lg: -12 }} mx={{ base: -4, lg: -12 }}
......
...@@ -9,11 +9,11 @@ import PageTitle from 'ui/shared/Page/PageTitle'; ...@@ -9,11 +9,11 @@ import PageTitle from 'ui/shared/Page/PageTitle';
import UserAvatar from 'ui/shared/UserAvatar'; import UserAvatar from 'ui/shared/UserAvatar';
const MyProfile = () => { const MyProfile = () => {
const { data, isLoading, isError } = useFetchProfileInfo(); const { data, isPending, isError } = useFetchProfileInfo();
useRedirectForInvalidAuthToken(); useRedirectForInvalidAuthToken();
const content = (() => { const content = (() => {
if (isLoading) { if (isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -54,7 +54,7 @@ const SearchResultsPageContent = () => { ...@@ -54,7 +54,7 @@ const SearchResultsPageContent = () => {
} }
} }
!redirectCheckQuery.isLoading && setShowContent(true); !redirectCheckQuery.isPending && setShowContent(true);
}, [ redirectCheckQuery, router, debouncedSearchTerm, showContent ]); }, [ redirectCheckQuery, router, debouncedSearchTerm, showContent ]);
const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => { const handleSubmit = React.useCallback((event: FormEvent<HTMLFormElement>) => {
......
...@@ -42,7 +42,7 @@ const WatchList: React.FC = () => { ...@@ -42,7 +42,7 @@ const WatchList: React.FC = () => {
}, [ addressModalProps ]); }, [ addressModalProps ]);
const onAddOrEditSuccess = useCallback(async() => { const onAddOrEditSuccess = useCallback(async() => {
await queryClient.refetchQueries([ resourceKey('watchlist') ]); await queryClient.refetchQueries({ queryKey: [ resourceKey('watchlist') ] });
setAddressModalData(undefined); setAddressModalData(undefined);
addressModalProps.onClose(); addressModalProps.onClose();
}, [ addressModalProps, queryClient ]); }, [ addressModalProps, queryClient ]);
......
...@@ -44,22 +44,23 @@ const AddressForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVisibl ...@@ -44,22 +44,23 @@ const AddressForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVisibl
const formBackgroundColor = useColorModeValue('white', 'gray.900'); const formBackgroundColor = useColorModeValue('white', 'gray.900');
const { mutate } = useMutation((formData: Inputs) => { const { mutate } = useMutation({
const body = { mutationFn: (formData: Inputs) => {
name: formData?.tag, const body = {
address_hash: formData?.address, name: formData?.tag,
}; address_hash: formData?.address,
};
const isEdit = data?.id; const isEdit = data?.id;
if (isEdit) { if (isEdit) {
return apiFetch('private_tags_address', { return apiFetch('private_tags_address', {
pathParams: { id: data.id }, pathParams: { id: data.id },
fetchParams: { method: 'PUT', body }, fetchParams: { method: 'PUT', body },
}); });
} }
return apiFetch('private_tags_address', { fetchParams: { method: 'POST', body } }); return apiFetch('private_tags_address', { fetchParams: { method: 'POST', body } });
}, { },
onError: (error: ResourceErrorAccount<AddressTagErrors>) => { onError: (error: ResourceErrorAccount<AddressTagErrors>) => {
setPending(false); setPending(false);
const errorMap = error.payload?.errors; const errorMap = error.payload?.errors;
......
...@@ -47,22 +47,23 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVi ...@@ -47,22 +47,23 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVi
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const { mutate } = useMutation((formData: Inputs) => { const { mutate } = useMutation({
const body = { mutationFn: (formData: Inputs) => {
name: formData?.tag, const body = {
transaction_hash: formData?.transaction, name: formData?.tag,
}; transaction_hash: formData?.transaction,
const isEdit = data?.id; };
const isEdit = data?.id;
if (isEdit) {
return apiFetch('private_tags_tx', { if (isEdit) {
pathParams: { id: data.id }, return apiFetch('private_tags_tx', {
fetchParams: { method: 'PUT', body }, pathParams: { id: data.id },
}); fetchParams: { method: 'PUT', body },
} });
}
return apiFetch('private_tags_tx', { fetchParams: { method: 'POST', body } });
}, { return apiFetch('private_tags_tx', { fetchParams: { method: 'POST', body } });
},
onError: (error: ResourceErrorAccount<TransactionTagErrors>) => { onError: (error: ResourceErrorAccount<TransactionTagErrors>) => {
setPending(false); setPending(false);
const errorMap = error.payload?.errors; const errorMap = error.payload?.errors;
...@@ -76,7 +77,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVi ...@@ -76,7 +77,7 @@ const TransactionForm: React.FC<Props> = ({ data, onClose, onSuccess, setAlertVi
} }
}, },
onSuccess: async() => { onSuccess: async() => {
await queryClient.refetchQueries([ resourceKey('private_tags_tx') ]); await queryClient.refetchQueries({ queryKey: [ resourceKey('private_tags_tx') ] });
await onSuccess(); await onSuccess();
onClose(); onClose();
setPending(false); setPending(false);
......
...@@ -109,7 +109,8 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -109,7 +109,8 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
}); });
}; };
const mutation = useMutation(updatePublicTag, { const mutation = useMutation({
mutationFn: updatePublicTag,
onSuccess: async(data) => { onSuccess: async(data) => {
const response = data as unknown as PublicTag; const response = data as unknown as PublicTag;
...@@ -237,7 +238,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => { ...@@ -237,7 +238,7 @@ const PublicTagsForm = ({ changeToDataScreen, data }: Props) => {
size="lg" size="lg"
type="submit" type="submit"
isDisabled={ !isDirty } isDisabled={ !isDirty }
isLoading={ mutation.isLoading } isLoading={ mutation.isPending }
> >
Send request Send request
</Button> </Button>
......
...@@ -39,7 +39,8 @@ const DeleteModal: React.FC<Props> = ({ ...@@ -39,7 +39,8 @@ const DeleteModal: React.FC<Props> = ({
onClose(); onClose();
}, [ onClose, setAlertVisible ]); }, [ onClose, setAlertVisible ]);
const mutation = useMutation(mutationFn, { const mutation = useMutation({
mutationFn,
onSuccess: async() => { onSuccess: async() => {
onSuccess(); onSuccess();
onClose(); onClose();
...@@ -70,7 +71,7 @@ const DeleteModal: React.FC<Props> = ({ ...@@ -70,7 +71,7 @@ const DeleteModal: React.FC<Props> = ({
<Button <Button
size="lg" size="lg"
onClick={ onDeleteClick } onClick={ onDeleteClick }
isLoading={ mutation.isLoading } isLoading={ mutation.isPending }
// FIXME: chackra's button is disabled when isLoading // FIXME: chackra's button is disabled when isLoading
isDisabled={ false } isDisabled={ false }
> >
......
...@@ -13,9 +13,9 @@ export default function useNftMediaType(url: string | null, isEnabled: boolean) ...@@ -13,9 +13,9 @@ export default function useNftMediaType(url: string | null, isEnabled: boolean)
const fetch = useFetch(); const fetch = useFetch();
const { data } = useQuery<unknown, ResourceError<unknown>, MediaType>( const { data } = useQuery<unknown, ResourceError<unknown>, MediaType>({
[ 'nft-media-type', url ], queryKey: [ 'nft-media-type', url ],
async() => { queryFn: async() => {
if (!url) { if (!url) {
return 'image'; return 'image';
} }
...@@ -41,10 +41,9 @@ export default function useNftMediaType(url: string | null, isEnabled: boolean) ...@@ -41,10 +41,9 @@ export default function useNftMediaType(url: string | null, isEnabled: boolean)
return 'image'; return 'image';
} }
}, },
{ enabled: isEnabled && Boolean(url),
enabled: isEnabled && Boolean(url), staleTime: Infinity,
staleTime: Infinity, });
});
return data; return data;
} }
...@@ -96,13 +96,12 @@ const Footer = () => { ...@@ -96,13 +96,12 @@ const Footer = () => {
const fetch = useFetch(); const fetch = useFetch();
const { isLoading, data: linksData } = useQuery<unknown, ResourceError<unknown>, Array<CustomLinksGroup>>( const { isPending, data: linksData } = useQuery<unknown, ResourceError<unknown>, Array<CustomLinksGroup>>({
[ 'footer-links' ], queryKey: [ 'footer-links' ],
async() => fetch(config.UI.footer.links || '', undefined, { resource: 'footer-links' }), queryFn: async() => fetch(config.UI.footer.links || '', undefined, { resource: 'footer-links' }),
{ enabled: Boolean(config.UI.footer.links),
enabled: Boolean(config.UI.footer.links), staleTime: Infinity,
staleTime: Infinity, });
});
return ( return (
<Flex <Flex
...@@ -170,7 +169,7 @@ const Footer = () => { ...@@ -170,7 +169,7 @@ const Footer = () => {
{ BLOCKSCOUT_LINKS.map(link => <FooterLinkItem { ...link } key={ link.text }/>) } { BLOCKSCOUT_LINKS.map(link => <FooterLinkItem { ...link } key={ link.text }/>) }
</Grid> </Grid>
</Box> </Box>
{ config.UI.footer.links && isLoading && ( { config.UI.footer.links && isPending && (
Array.from(Array(3)).map((i, index) => ( Array.from(Array(3)).map((i, index) => (
<Box minW="160px" key={ index }> <Box minW="160px" key={ index }>
<Skeleton w="120px" h="20px" mb={ 6 }/> <Skeleton w="120px" h="20px" mb={ 6 }/>
......
...@@ -13,7 +13,7 @@ import useSocketMessage from 'lib/socket/useSocketMessage'; ...@@ -13,7 +13,7 @@ import useSocketMessage from 'lib/socket/useSocketMessage';
const IntTxsIndexingStatus = () => { const IntTxsIndexingStatus = () => {
const { data, isError, isLoading } = useApiQuery('homepage_indexing_status'); const { data, isError, isPending } = useApiQuery('homepage_indexing_status');
const bgColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.100'); const bgColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.100');
const hintTextcolor = useColorModeValue('black', 'white'); const hintTextcolor = useColorModeValue('black', 'white');
...@@ -42,7 +42,7 @@ const IntTxsIndexingStatus = () => { ...@@ -42,7 +42,7 @@ const IntTxsIndexingStatus = () => {
handler: handleInternalTxsIndexStatus, handler: handleInternalTxsIndexStatus,
}); });
if (isError || isLoading) { if (isError || isPending) {
return null; return null;
} }
......
...@@ -18,17 +18,17 @@ const IndexingBlocksAlert = () => { ...@@ -18,17 +18,17 @@ const IndexingBlocksAlert = () => {
const cookiesString = appProps.cookies; const cookiesString = appProps.cookies;
const [ hasAlertCookie ] = React.useState(cookies.get(cookies.NAMES.INDEXING_ALERT, cookiesString) === 'true'); const [ hasAlertCookie ] = React.useState(cookies.get(cookies.NAMES.INDEXING_ALERT, cookiesString) === 'true');
const { data, isError, isLoading } = useApiQuery('homepage_indexing_status', { const { data, isError, isPending } = useApiQuery('homepage_indexing_status', {
queryOptions: { queryOptions: {
enabled: !config.UI.indexingAlert.blocks.isHidden, enabled: !config.UI.indexingAlert.blocks.isHidden,
}, },
}); });
React.useEffect(() => { React.useEffect(() => {
if (!isLoading && !isError) { if (!isPending && !isError) {
cookies.set(cookies.NAMES.INDEXING_ALERT, data.finished_indexing_blocks ? 'false' : 'true'); cookies.set(cookies.NAMES.INDEXING_ALERT, data.finished_indexing_blocks ? 'false' : 'true');
} }
}, [ data, isError, isLoading ]); }, [ data, isError, isPending ]);
const queryClient = useQueryClient(); const queryClient = useQueryClient();
...@@ -62,7 +62,7 @@ const IndexingBlocksAlert = () => { ...@@ -62,7 +62,7 @@ const IndexingBlocksAlert = () => {
return null; return null;
} }
if (isLoading) { if (isPending) {
return hasAlertCookie ? <Skeleton h={{ base: '96px', lg: '48px' }} w="100%"/> : null; return hasAlertCookie ? <Skeleton h={{ base: '96px', lg: '48px' }} w="100%"/> : null;
} }
......
...@@ -13,21 +13,20 @@ export default function useNetworkMenu() { ...@@ -13,21 +13,20 @@ export default function useNetworkMenu() {
const { isOpen, onClose, onOpen, onToggle } = useDisclosure(); const { isOpen, onClose, onOpen, onToggle } = useDisclosure();
const apiFetch = useApiFetch(); const apiFetch = useApiFetch();
const { isLoading, data } = useQuery<unknown, ResourceError<unknown>, Array<FeaturedNetwork>>( const { isPending, data } = useQuery<unknown, ResourceError<unknown>, Array<FeaturedNetwork>>({
[ 'featured-network' ], queryKey: [ 'featured-network' ],
async() => apiFetch(config.UI.sidebar.featuredNetworks || '', undefined, { resource: 'featured-network' }), queryFn: async() => apiFetch(config.UI.sidebar.featuredNetworks || '', undefined, { resource: 'featured-network' }),
{ enabled: Boolean(config.UI.sidebar.featuredNetworks) && isOpen,
enabled: Boolean(config.UI.sidebar.featuredNetworks) && isOpen, staleTime: Infinity,
staleTime: Infinity, });
});
return React.useMemo(() => ({ return React.useMemo(() => ({
isOpen, isOpen,
onClose, onClose,
onOpen, onOpen,
onToggle, onToggle,
isLoading, isPending,
data, data,
availableTabs: NETWORK_GROUPS.filter((tab) => data?.some(({ group }) => group === tab)), availableTabs: NETWORK_GROUPS.filter((tab) => data?.some(({ group }) => group === tab)),
}), [ isOpen, onClose, onOpen, onToggle, data, isLoading ]); }), [ isOpen, onClose, onOpen, onToggle, data, isPending ]);
} }
...@@ -9,15 +9,15 @@ import UserAvatar from 'ui/shared/UserAvatar'; ...@@ -9,15 +9,15 @@ import UserAvatar from 'ui/shared/UserAvatar';
import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent'; import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
const ProfileMenuDesktop = () => { const ProfileMenuDesktop = () => {
const { data, error, isLoading } = useFetchProfileInfo(); const { data, error, isPending } = useFetchProfileInfo();
const loginUrl = useLoginUrl(); const loginUrl = useLoginUrl();
const [ hasMenu, setHasMenu ] = React.useState(false); const [ hasMenu, setHasMenu ] = React.useState(false);
React.useEffect(() => { React.useEffect(() => {
if (!isLoading) { if (!isPending) {
setHasMenu(Boolean(data)); setHasMenu(Boolean(data));
} }
}, [ data, error?.status, isLoading ]); }, [ data, error?.status, isPending ]);
const handleSignInClick = React.useCallback(() => { const handleSignInClick = React.useCallback(() => {
mixpanel.logEvent( mixpanel.logEvent(
......
...@@ -11,7 +11,7 @@ import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent'; ...@@ -11,7 +11,7 @@ import ProfileMenuContent from 'ui/snippets/profileMenu/ProfileMenuContent';
const ProfileMenuMobile = () => { const ProfileMenuMobile = () => {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const { data, error, isLoading } = useFetchProfileInfo(); const { data, error, isPending } = useFetchProfileInfo();
const loginUrl = useLoginUrl(); const loginUrl = useLoginUrl();
const [ hasMenu, setHasMenu ] = React.useState(false); const [ hasMenu, setHasMenu ] = React.useState(false);
...@@ -24,10 +24,10 @@ const ProfileMenuMobile = () => { ...@@ -24,10 +24,10 @@ const ProfileMenuMobile = () => {
}, []); }, []);
React.useEffect(() => { React.useEffect(() => {
if (!isLoading) { if (!isPending) {
setHasMenu(Boolean(data)); setHasMenu(Boolean(data));
} }
}, [ data, error?.status, isLoading ]); }, [ data, error?.status, isPending ]);
const buttonProps: Partial<ButtonProps> = (() => { const buttonProps: Partial<ButtonProps> = (() => {
if (hasMenu || !loginUrl) { if (hasMenu || !loginUrl) {
......
...@@ -103,7 +103,7 @@ const SearchBarSuggest = ({ query, searchTerm, onItemClick, containerId }: Props ...@@ -103,7 +103,7 @@ const SearchBarSuggest = ({ query, searchTerm, onItemClick, containerId }: Props
const bgColor = useColorModeValue('white', 'gray.900'); const bgColor = useColorModeValue('white', 'gray.900');
const content = (() => { const content = (() => {
if (query.isLoading || marketplaceApps.isPlaceholderData) { if (query.isPending || marketplaceApps.isPlaceholderData) {
return <ContentLoader text="We are searching, please wait... " fontSize="sm"/>; return <ContentLoader text="We are searching, please wait... " fontSize="sm"/>;
} }
......
...@@ -71,7 +71,7 @@ const Sol2UmlDiagram = ({ addressHash }: Props) => { ...@@ -71,7 +71,7 @@ const Sol2UmlDiagram = ({ addressHash }: Props) => {
throw Error('Uml diagram fetch error', { cause: contractQuery.error as unknown as Error }); throw Error('Uml diagram fetch error', { cause: contractQuery.error as unknown as Error });
} }
if (contractQuery.isLoading || umlQuery.isLoading) { if (contractQuery.isPending || umlQuery.isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -27,7 +27,7 @@ const ChartWidgetContainer = ({ id, title, description, interval, onLoadingError ...@@ -27,7 +27,7 @@ const ChartWidgetContainer = ({ id, title, description, interval, onLoadingError
const endDate = selectedInterval.start ? formatDate(new Date()) : undefined; const endDate = selectedInterval.start ? formatDate(new Date()) : undefined;
const startDate = selectedInterval.start ? formatDate(selectedInterval.start) : undefined; const startDate = selectedInterval.start ? formatDate(selectedInterval.start) : undefined;
const { data, isLoading, isError } = useApiQuery('stats_line', { const { data, isPending, isError } = useApiQuery('stats_line', {
pathParams: { id }, pathParams: { id },
queryParams: { queryParams: {
from: startDate, from: startDate,
...@@ -56,7 +56,7 @@ const ChartWidgetContainer = ({ id, title, description, interval, onLoadingError ...@@ -56,7 +56,7 @@ const ChartWidgetContainer = ({ id, title, description, interval, onLoadingError
title={ title } title={ title }
units={ units } units={ units }
description={ description } description={ description }
isLoading={ isLoading } isLoading={ isPending }
minH="230px" minH="230px"
/> />
); );
......
...@@ -7,6 +7,7 @@ import { scroller } from 'react-scroll'; ...@@ -7,6 +7,7 @@ import { scroller } from 'react-scroll';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import { TOKEN_COUNTERS } from 'stubs/token'; import { TOKEN_COUNTERS } from 'stubs/token';
...@@ -18,7 +19,7 @@ import TruncatedValue from 'ui/shared/TruncatedValue'; ...@@ -18,7 +19,7 @@ import TruncatedValue from 'ui/shared/TruncatedValue';
import TokenNftMarketplaces from './TokenNftMarketplaces'; import TokenNftMarketplaces from './TokenNftMarketplaces';
interface Props { interface Props {
tokenQuery: UseQueryResult<TokenInfo>; tokenQuery: UseQueryResult<TokenInfo, ResourceError<unknown>>;
} }
const TokenDetails = ({ tokenQuery }: Props) => { const TokenDetails = ({ tokenQuery }: Props) => {
......
...@@ -5,24 +5,25 @@ import React from 'react'; ...@@ -5,24 +5,25 @@ import React from 'react';
import type { TokenVerifiedInfo as TTokenVerifiedInfo } from 'types/api/token'; import type { TokenVerifiedInfo as TTokenVerifiedInfo } from 'types/api/token';
import config from 'configs/app'; import config from 'configs/app';
import type { ResourceError } from 'lib/api/resources';
import LinkExternal from 'ui/shared/LinkExternal'; import LinkExternal from 'ui/shared/LinkExternal';
import TokenProjectInfo from './TokenProjectInfo'; import TokenProjectInfo from './TokenProjectInfo';
interface Props { interface Props {
verifiedInfoQuery: UseQueryResult<TTokenVerifiedInfo>; verifiedInfoQuery: UseQueryResult<TTokenVerifiedInfo, ResourceError<unknown>>;
} }
const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => { const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => {
const { data, isLoading, isError } = verifiedInfoQuery; const { data, isPending, isError } = verifiedInfoQuery;
const content = (() => { const content = (() => {
if (!config.features.verifiedTokens.isEnabled) { if (!config.features.verifiedTokens.isEnabled) {
return null; return null;
} }
if (isLoading) { if (isPending) {
return ( return (
<> <>
<Skeleton w="100px" h="30px" borderRadius="base"/> <Skeleton w="100px" h="30px" borderRadius="base"/>
......
...@@ -112,7 +112,7 @@ const TokenInfoForm = ({ address, tokenName, application, onSubmit }: Props) => ...@@ -112,7 +112,7 @@ const TokenInfoForm = ({ address, tokenName, application, onSubmit }: Props) =>
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
if (configQuery.isLoading) { if (configQuery.isPending) {
return <ContentLoader/>; return <ContentLoader/>;
} }
......
...@@ -24,7 +24,7 @@ const TxLogs = () => { ...@@ -24,7 +24,7 @@ const TxLogs = () => {
}, },
}); });
if (!txInfo.isLoading && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) { if (!txInfo.isPending && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) {
return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>; return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>;
} }
......
...@@ -49,7 +49,7 @@ const TxRawTrace = () => { ...@@ -49,7 +49,7 @@ const TxRawTrace = () => {
handler: handleRawTraceMessage, handler: handleRawTraceMessage,
}); });
if (!txInfo.isLoading && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) { if (!txInfo.isPending && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) {
return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>; return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>;
} }
......
...@@ -31,7 +31,7 @@ const TxState = () => { ...@@ -31,7 +31,7 @@ const TxState = () => {
}, },
}); });
if (!txInfo.isLoading && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) { if (!txInfo.isPending && !txInfo.isPlaceholderData && !txInfo.isError && !txInfo.data.status) {
return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>; return txInfo.socketStatus ? <TxSocketAlert status={ txInfo.socketStatus }/> : <TxPendingAlert/>;
} }
......
...@@ -45,7 +45,7 @@ const TxTokenTransfer = () => { ...@@ -45,7 +45,7 @@ const TxTokenTransfer = () => {
setTypeFilter(nextValue); setTypeFilter(nextValue);
}, [ tokenTransferQuery ]); }, [ tokenTransferQuery ]);
if (!txsInfo.isLoading && !txsInfo.isPlaceholderData && !txsInfo.isError && !txsInfo.data.status) { if (!txsInfo.isPending && !txsInfo.isPlaceholderData && !txsInfo.isError && !txsInfo.data.status) {
return txsInfo.socketStatus ? <TxSocketAlert status={ txsInfo.socketStatus }/> : <TxPendingAlert/>; return txsInfo.socketStatus ? <TxSocketAlert status={ txsInfo.socketStatus }/> : <TxPendingAlert/>;
} }
......
...@@ -38,7 +38,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params ...@@ -38,7 +38,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params
placeholderData: config.features.zkEvmRollup.isEnabled ? TX_ZKEVM_L2 : TX, placeholderData: config.features.zkEvmRollup.isEnabled ? TX_ZKEVM_L2 : TX,
}, },
}); });
const { data, isError, isLoading } = queryResult; const { data, isError, isPending } = queryResult;
const handleStatusUpdateMessage: SocketMessage.TxStatusUpdate['handler'] = React.useCallback(async() => { const handleStatusUpdateMessage: SocketMessage.TxStatusUpdate['handler'] = React.useCallback(async() => {
updateDelay && await delay(updateDelay); updateDelay && await delay(updateDelay);
...@@ -60,7 +60,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params ...@@ -60,7 +60,7 @@ export default function useFetchTxInfo({ onTxStatusUpdate, updateDelay }: Params
topic: `transactions:${ hash }`, topic: `transactions:${ hash }`,
onSocketClose: handleSocketClose, onSocketClose: handleSocketClose,
onSocketError: handleSocketError, onSocketError: handleSocketError,
isDisabled: isLoading || isError || data.status !== null, isDisabled: isPending || isError || data.status !== null,
}); });
useSocketMessage({ useSocketMessage({
channel, channel,
......
...@@ -11,14 +11,14 @@ interface Props { ...@@ -11,14 +11,14 @@ interface Props {
} }
const TxAdditionalInfoContainer = ({ hash }: Props) => { const TxAdditionalInfoContainer = ({ hash }: Props) => {
const { data, isError, isLoading } = useApiQuery('tx', { const { data, isError, isPending } = useApiQuery('tx', {
pathParams: { hash }, pathParams: { hash },
queryOptions: { queryOptions: {
refetchOnMount: false, refetchOnMount: false,
}, },
}); });
if (isLoading) { if (isPending) {
return ( return (
<Box> <Box>
<Skeleton w="130px" h="24px" borderRadius="full" mb={ 6 }/> <Skeleton w="130px" h="24px" borderRadius="full" mb={ 6 }/>
......
...@@ -4,17 +4,18 @@ import React from 'react'; ...@@ -4,17 +4,18 @@ import React from 'react';
import type { TxsResponse } from 'types/api/transaction'; import type { TxsResponse } from 'types/api/transaction';
import type { Sort } from 'types/client/txs-sort'; import type { Sort } from 'types/client/txs-sort';
import type { ResourceError } from 'lib/api/resources';
import * as cookies from 'lib/cookies'; import * as cookies from 'lib/cookies';
import sortTxs from 'lib/tx/sortTxs'; import sortTxs from 'lib/tx/sortTxs';
type HookResult = UseQueryResult<TxsResponse> & { type HookResult = UseQueryResult<TxsResponse, ResourceError<unknown>> & {
sorting: Sort; sorting: Sort;
setSortByField: (field: 'val' | 'fee') => () => void; setSortByField: (field: 'val' | 'fee') => () => void;
setSortByValue: (value: Sort | undefined) => void; setSortByValue: (value: Sort | undefined) => void;
} }
export default function useTxsSort( export default function useTxsSort(
queryResult: UseQueryResult<TxsResponse>, queryResult: UseQueryResult<TxsResponse, ResourceError<unknown>>,
): HookResult { ): HookResult {
const [ sorting, setSorting ] = React.useState<Sort>(cookies.get(cookies.NAMES.TXS_SORT) as Sort); const [ sorting, setSorting ] = React.useState<Sort>(cookies.get(cookies.NAMES.TXS_SORT) as Sort);
...@@ -61,7 +62,7 @@ export default function useTxsSort( ...@@ -61,7 +62,7 @@ export default function useTxsSort(
}, []); }, []);
return React.useMemo(() => { return React.useMemo(() => {
if (queryResult.isError || queryResult.isLoading) { if (queryResult.isError || queryResult.isPending) {
return { ...queryResult, setSortByField, setSortByValue, sorting }; return { ...queryResult, setSortByField, setSortByValue, sorting };
} }
......
...@@ -13,7 +13,7 @@ const VerifiedContractsCounters = () => { ...@@ -13,7 +13,7 @@ const VerifiedContractsCounters = () => {
} }
const content = (() => { const content = (() => {
if (countersQuery.isLoading) { if (countersQuery.isPending) {
const item = <Skeleton w={{ base: '100%', lg: 'calc((100% - 12px)/2)' }} h="69px" borderRadius="12px"/>; const item = <Skeleton w={{ base: '100%', lg: 'calc((100% - 12px)/2)' }} h="69px" borderRadius="12px"/>;
return ( return (
<> <>
......
...@@ -106,7 +106,8 @@ const AddressForm: React.FC<Props> = ({ data, onSuccess, setAlertVisible, isAdd ...@@ -106,7 +106,8 @@ const AddressForm: React.FC<Props> = ({ data, onSuccess, setAlertVisible, isAdd
} }
} }
const { mutate } = useMutation(updateWatchlist, { const { mutate } = useMutation({
mutationFn: updateWatchlist,
onSuccess: async() => { onSuccess: async() => {
await onSuccess(); await onSuccess();
setPending(false); setPending(false);
......
...@@ -59,15 +59,16 @@ const WatchListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) = ...@@ -59,15 +59,16 @@ const WatchListItem = ({ item, isLoading, onEditClick, onDeleteClick }: Props) =
}); });
}, [ notificationToast ]); }, [ notificationToast ]);
const { mutate } = useMutation(() => { const { mutate } = useMutation({
setSwitchDisabled(true); mutationFn: () => {
const body = { ...item, notification_methods: { email: !notificationEnabled } }; setSwitchDisabled(true);
setNotificationEnabled(prevState => !prevState); const body = { ...item, notification_methods: { email: !notificationEnabled } };
return apiFetch('watchlist', { setNotificationEnabled(prevState => !prevState);
pathParams: { id: item.id }, return apiFetch('watchlist', {
fetchParams: { method: 'PUT', body }, pathParams: { id: item.id },
}); fetchParams: { method: 'PUT', body },
}, { });
},
onError: () => { onError: () => {
showErrorToast(); showErrorToast();
setNotificationEnabled(prevState => !prevState); setNotificationEnabled(prevState => !prevState);
......
...@@ -63,15 +63,16 @@ const WatchlistTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Pro ...@@ -63,15 +63,16 @@ const WatchlistTableItem = ({ item, isLoading, onEditClick, onDeleteClick }: Pro
}); });
}, [ notificationToast ]); }, [ notificationToast ]);
const { mutate } = useMutation(() => { const { mutate } = useMutation({
setSwitchDisabled(true); mutationFn: () => {
const body = { ...item, notification_methods: { email: !notificationEnabled } }; setSwitchDisabled(true);
setNotificationEnabled(prevState => !prevState); const body = { ...item, notification_methods: { email: !notificationEnabled } };
return apiFetch('watchlist', { setNotificationEnabled(prevState => !prevState);
pathParams: { id: item.id }, return apiFetch('watchlist', {
fetchParams: { method: 'PUT', body }, pathParams: { id: item.id },
}); fetchParams: { method: 'PUT', body },
}, { });
},
onError: () => { onError: () => {
showErrorToast(); showErrorToast();
setNotificationEnabled(prevState => !prevState); setNotificationEnabled(prevState => !prevState);
......
This diff is collapsed.
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