Skip to content

Commit

Permalink
[frontend] upgrade to react-query v5 (#14346)
Browse files Browse the repository at this point in the history
## Description 

This PR upgrades our codebase and frontend SDKs to use react-query v5
which was released yesterday. @Jordan-Mysten did 98% of the work here
(thx bud), but to cover the migration list/changes here:

https://tanstack.com/query/v5/docs/react/guides/migrating-to-v5

- Explicitly set `initialPageParam` to null for all infinite queries
(this starts us at the first page)
- Modified typings for `useSuiClientQuery` and
`useSuiClientInfiniteQuery` to support data transformations via `select`
- Removed onSuccess, onError, onSettled callbacks on `useQuery` in favor
of side effects
- Renamed `isLoading` -> `isPending` which would be equivalent in the
pre-v5 world
- Replaced deprecated `isInitialLoading` with `isLoading` which is now
equivalent
- Replaced `keepPreviousData` property with `placeholderData:
keepPreviousData`
 - Replaced `dehydrateQueries` with `shouldDehydrateQuery`
 - Renamed `cacheTime` -> `gcTime`


As a side note, the whole `isPending` vs `isLoading` concept is pretty
confusing to wrap your ahead around. I didn't change anything
functionality-wise, but that isn't to say that we're using the correct
status field everywhere in our codebase:

`isPending` = no data is available (e.g. the query is disabled)
`isLoading` = we're actively fetching data

## Test Plan 
- Going to manually test all of our applications and core flows work as
expected just in case we missed something
- Won't land this until next week when we've done said testing ^
- Existing tests
- CI

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: Jordan Gensler <[email protected]>
  • Loading branch information
williamrobertson13 and Jordan-Mysten authored Oct 24, 2023
1 parent fda8225 commit d4d9c92
Show file tree
Hide file tree
Showing 151 changed files with 668 additions and 636 deletions.
6 changes: 6 additions & 0 deletions .changeset/khaki-monkeys-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@mysten/create-dapp': minor
'@mysten/dapp-kit': minor
---

Upgrade dapp-kit and the scaffold applications to react-query v5
2 changes: 1 addition & 1 deletion apps/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@mysten/kiosk": "workspace:*",
"@mysten/sui.js": "workspace:*",
"@sentry/react": "^7.59.2",
"@tanstack/react-query": "^4.29.25",
"@tanstack/react-query": "^5.0.0",
"bignumber.js": "^9.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/core/src/hooks/useFormatCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function useCoinMetadata(coinType?: string | null) {
retry: false,
enabled: !!coinType,
staleTime: Infinity,
cacheTime: 24 * 60 * 60 * 1000,
gcTime: 24 * 60 * 60 * 1000,
});
}

Expand Down
26 changes: 10 additions & 16 deletions apps/core/src/hooks/useGetCoins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,27 @@

import { useSuiClient } from '@mysten/dapp-kit';
import { PaginatedCoins } from '@mysten/sui.js/client';
import { useInfiniteQuery, UseInfiniteQueryResult } from '@tanstack/react-query';
import { useInfiniteQuery } from '@tanstack/react-query';

const MAX_COINS_PER_REQUEST = 10;

export function useGetCoins(
coinType: string,
address?: string | null,
maxCoinsPerRequest = MAX_COINS_PER_REQUEST,
): UseInfiniteQueryResult<PaginatedCoins> {
) {
const client = useSuiClient();
return useInfiniteQuery(
['get-coins', address, coinType, maxCoinsPerRequest],
({ pageParam }) =>
return useInfiniteQuery<PaginatedCoins>({
queryKey: ['get-coins', address, coinType, maxCoinsPerRequest],
initialPageParam: null,
getNextPageParam: ({ hasNextPage, nextCursor }) => (hasNextPage ? nextCursor : null),
queryFn: ({ pageParam }) =>
client.getCoins({
owner: address!,
coinType,
cursor: pageParam ? pageParam.cursor : null,
cursor: pageParam as string | null,
limit: maxCoinsPerRequest,
}),
{
getNextPageParam: ({ hasNextPage, nextCursor }) =>
hasNextPage
? {
cursor: nextCursor,
}
: false,
enabled: !!address,
},
);
enabled: !!address,
});
}
2 changes: 1 addition & 1 deletion apps/core/src/hooks/useGetDelegatedStake.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useQuery, type UseQueryOptions } from '@tanstack/react-query';

type UseGetDelegatedStakesOptions = {
address: string;
} & UseQueryOptions<DelegatedStake[], Error>;
} & Omit<UseQueryOptions<DelegatedStake[], Error>, 'queryKey' | 'queryFn'>;

export function useGetDelegatedStake(options: UseGetDelegatedStakesOptions) {
const client = useSuiClient();
Expand Down
18 changes: 9 additions & 9 deletions apps/core/src/hooks/useGetDynamicFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@
// SPDX-License-Identifier: Apache-2.0

import { useSuiClient } from '@mysten/dapp-kit';
import { DynamicFieldPage } from '@mysten/sui.js/src/client';
import { normalizeSuiAddress } from '@mysten/sui.js/utils';
import { useInfiniteQuery } from '@tanstack/react-query';

const MAX_PAGE_SIZE = 10;

export function useGetDynamicFields(parentId: string, maxPageSize = MAX_PAGE_SIZE) {
const client = useSuiClient();
return useInfiniteQuery(
['dynamic-fields', parentId],
({ pageParam = null }) =>
return useInfiniteQuery<DynamicFieldPage>({
queryKey: ['dynamic-fields', { maxPageSize, parentId }],
queryFn: ({ pageParam = null }) =>
client.getDynamicFields({
parentId: normalizeSuiAddress(parentId),
cursor: pageParam,
cursor: pageParam as string | null,
limit: maxPageSize,
}),
{
enabled: !!parentId,
getNextPageParam: ({ nextCursor, hasNextPage }) => (hasNextPage ? nextCursor : null),
},
);
enabled: !!parentId,
initialPageParam: null,
getNextPageParam: ({ nextCursor, hasNextPage }) => (hasNextPage ? nextCursor : null),
});
}
22 changes: 11 additions & 11 deletions apps/core/src/hooks/useGetOwnedObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { useSuiClient } from '@mysten/dapp-kit';
import { type SuiObjectDataFilter } from '@mysten/sui.js/client';
import { PaginatedObjectsResponse, type SuiObjectDataFilter } from '@mysten/sui.js/client';
import { useInfiniteQuery } from '@tanstack/react-query';

const MAX_OBJECTS_PER_REQ = 6;
Expand All @@ -13,9 +13,10 @@ export function useGetOwnedObjects(
maxObjectRequests = MAX_OBJECTS_PER_REQ,
) {
const client = useSuiClient();
return useInfiniteQuery(
['get-owned-objects', address, filter, maxObjectRequests],
({ pageParam }) =>
return useInfiniteQuery<PaginatedObjectsResponse>({
initialPageParam: null,
queryKey: ['get-owned-objects', address, filter, maxObjectRequests],
queryFn: ({ pageParam }) =>
client.getOwnedObjects({
owner: address!,
filter,
Expand All @@ -25,12 +26,11 @@ export function useGetOwnedObjects(
showDisplay: true,
},
limit: maxObjectRequests,
cursor: pageParam,
cursor: pageParam as string | null,
}),
{
staleTime: 10 * 1000,
enabled: !!address,
getNextPageParam: (lastPage) => (lastPage?.hasNextPage ? lastPage.nextCursor : null),
},
);

staleTime: 10 * 1000,
enabled: !!address,
getNextPageParam: ({ hasNextPage, nextCursor }) => (hasNextPage ? nextCursor : null),
});
}
8 changes: 4 additions & 4 deletions apps/core/src/hooks/useMultiGetObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
// SPDX-License-Identifier: Apache-2.0

import { useSuiClient } from '@mysten/dapp-kit';
import { SuiObjectDataOptions } from '@mysten/sui.js/src/client';
import { useQuery } from '@tanstack/react-query';
import { SuiObjectDataOptions, SuiObjectResponse } from '@mysten/sui.js/client';
import { useQuery, UseQueryOptions } from '@tanstack/react-query';

import { chunkArray } from '../utils/chunkArray';

export function useMultiGetObjects(
ids: string[],
options: SuiObjectDataOptions,
queryOptions?: { keepPreviousData?: boolean },
queryOptions?: Omit<UseQueryOptions<SuiObjectResponse[]>, 'queryKey' | 'queryFn'>,
) {
const client = useSuiClient();
return useQuery({
...queryOptions,
queryKey: ['multiGetObjects', ids],
queryFn: async () => {
const responses = await Promise.all(
Expand All @@ -27,6 +28,5 @@ export function useMultiGetObjects(
return responses.flat();
},
enabled: !!ids?.length,
...queryOptions,
});
}
2 changes: 1 addition & 1 deletion apps/core/src/hooks/useProductAnalyticsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ export function useProductAnalyticsConfig() {
queryKey: ['apps-backend', 'product-analytics-config'],
queryFn: () => request<ProductAnalyticsConfigResponse>('product-analytics'),
staleTime: 24 * 60 * 60 * 1000,
cacheTime: Infinity,
gcTime: Infinity,
});
}
2 changes: 1 addition & 1 deletion apps/core/src/hooks/useSuiCoinData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function useSuiCoinData() {
return useQuery({
queryKey: ['sui-coin-data'],
queryFn: () => request<CoinData>('coins/sui', {}),
cacheTime: 24 * 60 * 60 * 1000,
gcTime: 24 * 60 * 60 * 1000,
staleTime: Infinity,
});
}
4 changes: 2 additions & 2 deletions apps/explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@sentry/react": "^7.59.2",
"@tanstack/react-query": "^4.29.25",
"@tanstack/react-query-devtools": "^4.29.25",
"@tanstack/react-query": "^5.0.0",
"@tanstack/react-query-devtools": "^5.0.1",
"@tanstack/react-table": "^8.9.3",
"@types/d3-array": "^3.0.5",
"@types/throttle-debounce": "^5.0.0",
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/components/AccountCardGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function TooltipContent({ data }: { data: AllEpochsAddressMetrics[number] }) {

export function AccountsCardGraph() {
const { data: addressMetrics } = useGetAddressMetrics();
const { data: allEpochMetrics, isLoading } = useGetAllEpochAddressMetrics({
const { data: allEpochMetrics, isPending } = useGetAllEpochAddressMetrics({
descendingOrder: false,
});
const adjEpochAddressMetrics = useMemo(() => allEpochMetrics?.slice(-30), [allEpochMetrics]);
Expand Down Expand Up @@ -77,7 +77,7 @@ export function AccountsCardGraph() {
!adjEpochAddressMetrics?.length && 'bg-gray-40',
)}
>
{isLoading ? (
{isPending ? (
<div className="flex flex-col items-center gap-1">
<LoadingIndicator />
<Text color="steel" variant="body/medium">
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/components/Activity/EpochsActivityTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function EpochsActivityTable({
});

const epochs = useGetEpochs(limit);
const { data, isFetching, pagination, isLoading, isError } = useCursorPagination(epochs);
const { data, isFetching, pagination, isPending, isError } = useCursorPagination(epochs);

const cardData = data ? genTableDataFromEpochsData(data) : undefined;

Expand All @@ -46,7 +46,7 @@ export function EpochsActivityTable({
{isError && (
<div className="pt-2 font-sans font-semibold text-issue-dark">Failed to load Epochs</div>
)}
{isLoading || isFetching || !cardData ? (
{isPending || isFetching || !cardData ? (
<PlaceholderTable
rowCount={limit}
rowHeight="16px"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function TransactionsActivityTable({
const { data: count } = useQuery({
queryKey: ['transactions', 'count'],
queryFn: () => client.getTotalTransactionBlocks(),
cacheTime: 24 * 60 * 60 * 1000,
gcTime: 24 * 60 * 60 * 1000,
staleTime: Infinity,
retry: false,
});
Expand All @@ -44,7 +44,7 @@ export function TransactionsActivityTable({
limit,
refetchInterval,
);
const { data, isFetching, pagination, isLoading, isError } = useCursorPagination(transactions);
const { data, isFetching, pagination, isPending, isError } = useCursorPagination(transactions);
const goToFirstPageRef = useRef(pagination.onFirst);
goToFirstPageRef.current = pagination.onFirst;
const cardData = data ? genTableDataFromTxData(data.data) : undefined;
Expand All @@ -60,7 +60,7 @@ export function TransactionsActivityTable({
</div>
)}
<div className="flex flex-col space-y-3 text-left">
{isLoading || isFetching || !cardData ? (
{isPending || isFetching || !cardData ? (
<PlaceholderTable
rowCount={limit}
rowHeight="16px"
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/components/HomeMetrics/Checkpoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import { StatsWrapper } from './FormattedStatsAmount';
import { useGetNetworkMetrics } from '~/hooks/useGetNetworkMetrics';

export function Checkpoint() {
const { data, isLoading } = useGetNetworkMetrics();
const { data, isPending } = useGetNetworkMetrics();

return (
<StatsWrapper
label="Checkpoint"
tooltip="The current checkpoint"
unavailable={isLoading}
unavailable={isPending}
size="sm"
orientation="horizontal"
>
Expand Down
6 changes: 3 additions & 3 deletions apps/explorer/src/components/Object/UnderlyingObjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function UnderlyingObjectCard({
name,
dynamicFieldType,
}: UnderlyingObjectCardProps) {
const { data, isLoading, isError, isFetched } = useSuiClientQuery('getDynamicFieldObject', {
const { data, isPending, isError, isFetched } = useSuiClientQuery('getDynamicFieldObject', {
parentId,
name,
});
Expand All @@ -35,14 +35,14 @@ export function UnderlyingObjectCard({
const {
data: normalizedStruct,
isFetched: normalizedStructFetched,
isLoading: loadingNormalizedStruct,
isPending: loadingNormalizedStruct,
} = useSuiClientQuery('getNormalizedMoveStruct', {
package: packageId,
module: moduleName,
struct: functionName,
});

const isDataLoading = isLoading || loadingNormalizedStruct;
const isDataLoading = isPending || loadingNormalizedStruct;

// Check for error first before showing the loading spinner to avoid infinite loading if GetDynamicFieldObject fails
if (
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/components/OwnedCoins/OwnedCoinsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export default function CoinsPanel({ coinType, id }: CoinsPanelProps) {
const containerRef = useRef(null);
const coinsSectionRef = useRef(null);
const { isIntersecting } = useOnScreen(containerRef);
const { data, isLoading, isFetching, fetchNextPage, hasNextPage } = useGetCoins(coinType, id);
const { data, isPending, isFetching, fetchNextPage, hasNextPage } = useGetCoins(coinType, id);
const [_, containerWidth] = useElementDimensions(coinsSectionRef);

const isSpinnerVisible = hasNextPage || isLoading || isFetching;
const isSpinnerVisible = hasNextPage || isPending || isFetching;

useEffect(() => {
if (isIntersecting && hasNextPage && !isFetching) {
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/src/components/OwnedCoins/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function OwnedCoins({ id }: { id: string }) {
const [currentSlice, setCurrentSlice] = useState(1);
const [limit, setLimit] = useState(20);
const [filterValue, setFilterValue] = useState(COIN_FILTERS.RECOGNIZED);
const { isLoading, data, isError } = useSuiClientQuery('getAllBalances', {
const { isPending, data, isError } = useSuiClientQuery('getAllBalances', {
owner: normalizeSuiAddress(id),
});
const recognizedPackages = useRecognizedPackages();
Expand Down Expand Up @@ -97,7 +97,7 @@ export function OwnedCoins({ id }: { id: string }) {

return (
<div className="h-full w-full md:pr-10">
{isLoading ? (
{isPending ? (
<div className="m-auto flex h-full w-full justify-center text-white">
<LoadingIndicator />
</div>
Expand Down
Loading

5 comments on commit d4d9c92

@vercel
Copy link

@vercel vercel bot commented on d4d9c92 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

sui-kiosk – ./dapps/kiosk

sui-kiosk-git-main-mysten-labs.vercel.app
sui-kiosk.vercel.app
sui-kiosk-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on d4d9c92 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on d4d9c92 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on d4d9c92 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

mysten-ui – ./apps/ui

mysten-ui-mysten-labs.vercel.app
mysten-ui.vercel.app
mysten-ui-git-main-mysten-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on d4d9c92 Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.