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,
|
t,
|
||||||
titlefy,
|
titlefy,
|
||||||
useDataProvider,
|
useDataProvider,
|
||||||
|
useThrottledDataProvider,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import type {
|
import type {
|
||||||
@ -31,7 +32,47 @@ export interface SingleMarketData extends SingleMarketFieldsFragment {
|
|||||||
data: MarketData;
|
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 { marketId } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -39,9 +80,6 @@ export const Market = () => {
|
|||||||
const update = useGlobalStore((store) => store.update);
|
const update = useGlobalStore((store) => store.update);
|
||||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||||
|
|
||||||
const pageTitle = usePageTitleStore((store) => store.pageTitle);
|
|
||||||
const updateTitle = usePageTitleStore((store) => store.updateTitle);
|
|
||||||
|
|
||||||
const onSelect = useCallback(
|
const onSelect = useCallback(
|
||||||
(id: string) => {
|
(id: string) => {
|
||||||
if (id && id !== marketId) {
|
if (id && id !== marketId) {
|
||||||
@ -51,56 +89,20 @@ export const Market = () => {
|
|||||||
[marketId, navigate]
|
[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<
|
const { data, error, loading } = useDataProvider<
|
||||||
SingleMarketFieldsFragment,
|
SingleMarketFieldsFragment,
|
||||||
never
|
never
|
||||||
>({
|
>({
|
||||||
dataProvider: marketProvider,
|
dataProvider: marketProvider,
|
||||||
variables,
|
variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]),
|
||||||
update: updateMarketId,
|
|
||||||
skip: !marketId,
|
skip: !marketId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const marketName = data?.tradableInstrument.instrument.name;
|
useEffect(() => {
|
||||||
const updateProvider = useCallback(
|
if (data?.id && data.id !== lastMarketId) {
|
||||||
({ data: marketData }: { data: MarketData | null }) => {
|
update({ marketId: data.id });
|
||||||
const marketPrice = calculatePrice(
|
}
|
||||||
marketData?.markPrice,
|
}, [update, lastMarketId, data?.id]);
|
||||||
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tradeView = useMemo(() => {
|
const tradeView = useMemo(() => {
|
||||||
if (w > 960) {
|
if (w > 960) {
|
||||||
@ -123,6 +125,11 @@ export const Market = () => {
|
|||||||
data={data || undefined}
|
data={data || undefined}
|
||||||
noDataCondition={(data) => false}
|
noDataCondition={(data) => false}
|
||||||
>
|
>
|
||||||
|
<TitleUpdater
|
||||||
|
marketId={data?.id}
|
||||||
|
marketName={data?.tradableInstrument.instrument.name}
|
||||||
|
decimalPlaces={data?.decimalPlaces}
|
||||||
|
/>
|
||||||
{tradeView}
|
{tradeView}
|
||||||
</AsyncRenderer>
|
</AsyncRenderer>
|
||||||
);
|
);
|
||||||
|
@ -17,15 +17,11 @@ export const useAccountBalance = (assetId?: string) => {
|
|||||||
const account = assetId
|
const account = assetId
|
||||||
? getSettlementAccount({ accounts: data, assetId })
|
? getSettlementAccount({ accounts: data, assetId })
|
||||||
: undefined;
|
: undefined;
|
||||||
if (accountBalance !== account?.balance) {
|
setAccountBalance(account?.balance || '');
|
||||||
setAccountBalance(account?.balance || '');
|
setAccountDecimals(account?.asset.decimals || null);
|
||||||
}
|
|
||||||
if (accountDecimals !== account?.asset.decimals) {
|
|
||||||
setAccountDecimals(account?.asset.decimals || null);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[accountBalance, accountDecimals, assetId]
|
[assetId]
|
||||||
);
|
);
|
||||||
|
|
||||||
useDataProvider({
|
useDataProvider({
|
||||||
|
@ -161,6 +161,13 @@ describe('useDataProvider hook', () => {
|
|||||||
});
|
});
|
||||||
expect(update).toBeCalledTimes(1);
|
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
|
// changing variables after date was loaded
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
rerender({ dataProvider, update, variables: { partyId: '0x321' } });
|
rerender({ dataProvider, update, variables: { partyId: '0x321' } });
|
||||||
@ -173,7 +180,7 @@ describe('useDataProvider hook', () => {
|
|||||||
await act(async () => {
|
await act(async () => {
|
||||||
callback({ ...updateCallbackPayload });
|
callback({ ...updateCallbackPayload });
|
||||||
});
|
});
|
||||||
expect(update).toBeCalledTimes(2);
|
expect(update).toBeCalledTimes(3);
|
||||||
|
|
||||||
// changing variables, apollo query will return error
|
// changing variables, apollo query will return error
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@ -193,7 +200,7 @@ describe('useDataProvider hook', () => {
|
|||||||
pageInfo: null,
|
pageInfo: null,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
expect(update).toBeCalledTimes(3);
|
expect(update).toBeCalledTimes(5);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('do not create data provider instance when skip is true', async () => {
|
it('do not create data provider instance when skip is true', async () => {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
|
import isEqual from 'lodash/isEqual';
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
import { usePrevious } from './use-previous';
|
||||||
import type { OperationVariables } from '@apollo/client';
|
import type { OperationVariables } from '@apollo/client';
|
||||||
import type {
|
import type {
|
||||||
Subscribe,
|
Subscribe,
|
||||||
@ -52,9 +54,9 @@ export const useDataProvider = <
|
|||||||
dataProvider,
|
dataProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
variables,
|
|
||||||
skipUpdates,
|
skipUpdates,
|
||||||
skip,
|
skip,
|
||||||
|
...props
|
||||||
}: useDataProviderParams<Data, Delta, Variables>) => {
|
}: useDataProviderParams<Data, Delta, Variables>) => {
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const [data, setData] = useState<Data | null>(null);
|
const [data, setData] = useState<Data | null>(null);
|
||||||
@ -65,6 +67,13 @@ export const useDataProvider = <
|
|||||||
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
|
const reloadRef = useRef<((force?: boolean) => void) | undefined>(undefined);
|
||||||
const loadRef = useRef<Load<Data> | undefined>(undefined);
|
const loadRef = useRef<Load<Data> | undefined>(undefined);
|
||||||
const initialized = useRef<boolean>(false);
|
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(() => {
|
const flush = useCallback(() => {
|
||||||
if (flushRef.current) {
|
if (flushRef.current) {
|
||||||
flushRef.current();
|
flushRef.current();
|
||||||
@ -125,6 +134,9 @@ export const useDataProvider = <
|
|||||||
setData(null);
|
setData(null);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
setTotalCount(undefined);
|
setTotalCount(undefined);
|
||||||
|
if (initialized.current && update) {
|
||||||
|
update({ data: null });
|
||||||
|
}
|
||||||
initialized.current = false;
|
initialized.current = false;
|
||||||
if (skip) {
|
if (skip) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user