feat: call update with null data from useDataProvider hook on variables change (#2689)
This commit is contained in:
parent
31881f8e5a
commit
0cff5895c7
@ -1,3 +1,3 @@
|
||||
import { Market } from './market';
|
||||
import { MarketPage } from './market';
|
||||
|
||||
export default Market;
|
||||
export default MarketPage;
|
||||
|
@ -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<MarketData, MarketDataUpdateFieldsFragment>({
|
||||
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}
|
||||
>
|
||||
<TitleUpdater
|
||||
marketId={data?.id}
|
||||
marketName={data?.tradableInstrument.instrument.name}
|
||||
decimalPlaces={data?.decimalPlaces}
|
||||
/>
|
||||
{tradeView}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
|
@ -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({
|
||||
|
@ -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 () => {
|
||||
|
@ -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<Data, Delta, Variables>) => {
|
||||
const client = useApolloClient();
|
||||
const [data, setData] = useState<Data | null>(null);
|
||||
@ -65,6 +67,13 @@ export const useDataProvider = <
|
||||
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
|
||||
const loadRef = useRef<Load<Data> | undefined>(undefined);
|
||||
const initialized = useRef<boolean>(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);
|
||||
|
Loading…
Reference in New Issue
Block a user