diff --git a/apps/trading/client-pages/market/index.ts b/apps/trading/client-pages/market/index.ts index 65cd500bc..22af22088 100644 --- a/apps/trading/client-pages/market/index.ts +++ b/apps/trading/client-pages/market/index.ts @@ -1,3 +1,3 @@ -import { Market } from './market'; +import { MarketPage } from './market'; -export default Market; +export default MarketPage; diff --git a/apps/trading/client-pages/market/market.tsx b/apps/trading/client-pages/market/market.tsx index 0fad3d26c..8fb170cd5 100644 --- a/apps/trading/client-pages/market/market.tsx +++ b/apps/trading/client-pages/market/market.tsx @@ -5,6 +5,7 @@ import { t, titlefy, useDataProvider, + useThrottledDataProvider, } from '@vegaprotocol/react-helpers'; import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit'; import type { @@ -31,7 +32,47 @@ export interface SingleMarketData extends SingleMarketFieldsFragment { data: MarketData; } -export const Market = () => { +const TitleUpdater = ({ + marketId, + marketName, + decimalPlaces, +}: { + marketId?: string; + marketName?: string; + decimalPlaces?: number; +}) => { + const pageTitle = usePageTitleStore((store) => store.pageTitle); + const updateTitle = usePageTitleStore((store) => store.updateTitle); + const { data: marketData } = useThrottledDataProvider< + MarketData, + MarketDataUpdateFieldsFragment + >( + { + dataProvider: marketDataProvider, + variables: useMemo(() => ({ marketId }), [marketId]), + skip: !marketId, + }, + 1000 + ); + useEffect(() => { + const marketPrice = calculatePrice(marketData?.markPrice, decimalPlaces); + if (marketName) { + const newPageTitle = titlefy([marketName, marketPrice]); + if (pageTitle !== newPageTitle) { + updateTitle(newPageTitle); + } + } + }, [ + decimalPlaces, + marketName, + marketData?.markPrice, + pageTitle, + updateTitle, + ]); + return null; +}; + +export const MarketPage = () => { const { marketId } = useParams(); const navigate = useNavigate(); @@ -39,9 +80,6 @@ export const Market = () => { const update = useGlobalStore((store) => store.update); const lastMarketId = useGlobalStore((store) => store.marketId); - const pageTitle = usePageTitleStore((store) => store.pageTitle); - const updateTitle = usePageTitleStore((store) => store.updateTitle); - const onSelect = useCallback( (id: string) => { if (id && id !== marketId) { @@ -51,56 +89,20 @@ export const Market = () => { [marketId, navigate] ); - const variables = useMemo( - () => ({ - marketId: marketId || '', - }), - [marketId] - ); - - const updateMarketId = useCallback( - ({ data }: { data: { id?: string } | null }) => { - if (data?.id && data.id !== lastMarketId) { - update({ marketId: data.id }); - } - return true; - }, - [update, lastMarketId] - ); const { data, error, loading } = useDataProvider< SingleMarketFieldsFragment, never >({ dataProvider: marketProvider, - variables, - update: updateMarketId, + variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]), skip: !marketId, }); - const marketName = data?.tradableInstrument.instrument.name; - const updateProvider = useCallback( - ({ data: marketData }: { data: MarketData | null }) => { - const marketPrice = calculatePrice( - marketData?.markPrice, - data?.decimalPlaces - ); - if (marketName) { - const newPageTitle = titlefy([marketName, marketPrice]); - if (pageTitle !== newPageTitle) { - updateTitle(newPageTitle); - } - } - return true; - }, - [updateTitle, pageTitle, marketName, data?.decimalPlaces] - ); - - useDataProvider({ - dataProvider: marketDataProvider, - update: updateProvider, - variables, - skip: !marketId || !data, - }); + useEffect(() => { + if (data?.id && data.id !== lastMarketId) { + update({ marketId: data.id }); + } + }, [update, lastMarketId, data?.id]); const tradeView = useMemo(() => { if (w > 960) { @@ -123,6 +125,11 @@ export const Market = () => { data={data || undefined} noDataCondition={(data) => false} > + {tradeView} ); diff --git a/libs/accounts/src/lib/use-account-balance.tsx b/libs/accounts/src/lib/use-account-balance.tsx index 1fb706996..d824652c6 100644 --- a/libs/accounts/src/lib/use-account-balance.tsx +++ b/libs/accounts/src/lib/use-account-balance.tsx @@ -17,15 +17,11 @@ export const useAccountBalance = (assetId?: string) => { const account = assetId ? getSettlementAccount({ accounts: data, assetId }) : undefined; - if (accountBalance !== account?.balance) { - setAccountBalance(account?.balance || ''); - } - if (accountDecimals !== account?.asset.decimals) { - setAccountDecimals(account?.asset.decimals || null); - } + setAccountBalance(account?.balance || ''); + setAccountDecimals(account?.asset.decimals || null); return true; }, - [accountBalance, accountDecimals, assetId] + [assetId] ); useDataProvider({ diff --git a/libs/react-helpers/src/hooks/use-data-provider.spec.ts b/libs/react-helpers/src/hooks/use-data-provider.spec.ts index dda3aa405..47aee7a78 100644 --- a/libs/react-helpers/src/hooks/use-data-provider.spec.ts +++ b/libs/react-helpers/src/hooks/use-data-provider.spec.ts @@ -161,6 +161,13 @@ describe('useDataProvider hook', () => { }); expect(update).toBeCalledTimes(1); + // setting same variables, with different object reference + await act(async () => { + rerender({ dataProvider, update, variables: { ...variables } }); + }); + expect(unsubscribe).toBeCalledTimes(0); + expect(dataProvider).toBeCalledTimes(1); + // changing variables after date was loaded await act(async () => { rerender({ dataProvider, update, variables: { partyId: '0x321' } }); @@ -173,7 +180,7 @@ describe('useDataProvider hook', () => { await act(async () => { callback({ ...updateCallbackPayload }); }); - expect(update).toBeCalledTimes(2); + expect(update).toBeCalledTimes(3); // changing variables, apollo query will return error await act(async () => { @@ -193,7 +200,7 @@ describe('useDataProvider hook', () => { pageInfo: null, }); }); - expect(update).toBeCalledTimes(3); + expect(update).toBeCalledTimes(5); }); it('do not create data provider instance when skip is true', async () => { diff --git a/libs/react-helpers/src/hooks/use-data-provider.ts b/libs/react-helpers/src/hooks/use-data-provider.ts index e28a1c6de..af8d91fc3 100644 --- a/libs/react-helpers/src/hooks/use-data-provider.ts +++ b/libs/react-helpers/src/hooks/use-data-provider.ts @@ -1,6 +1,8 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import throttle from 'lodash/throttle'; +import isEqual from 'lodash/isEqual'; import { useApolloClient } from '@apollo/client'; +import { usePrevious } from './use-previous'; import type { OperationVariables } from '@apollo/client'; import type { Subscribe, @@ -52,9 +54,9 @@ export const useDataProvider = < dataProvider, update, insert, - variables, skipUpdates, skip, + ...props }: useDataProviderParams) => { const client = useApolloClient(); const [data, setData] = useState(null); @@ -65,6 +67,13 @@ export const useDataProvider = < const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined); const loadRef = useRef | undefined>(undefined); const initialized = useRef(false); + const prevVariables = usePrevious(props.variables); + const [variables, setVariables] = useState(props.variables); + useEffect(() => { + if (!isEqual(prevVariables, props.variables)) { + setVariables(props.variables); + } + }, [props.variables, prevVariables]); const flush = useCallback(() => { if (flushRef.current) { flushRef.current(); @@ -125,6 +134,9 @@ export const useDataProvider = < setData(null); setError(undefined); setTotalCount(undefined); + if (initialized.current && update) { + update({ data: null }); + } initialized.current = false; if (skip) { setLoading(false);